zoukankan      html  css  js  c++  java
  • C++编程练习(15)----“排序算法 之 归并排序“

    归并排序

    归并排序(Merging Sort)的原理:

    假设初始序列含有 n 个记录,则可以看成是 n 个有序的子序列,每个子序列的长度为1,然后两两归并,得到 [n/2] ([ x ] 表示不小于 x 的最小整数)个长度为 2 或 1 的有序子序列;再两两归并,·······,如此重复,直至得到一个长度为 n 的有序序列为止,这种排序方法称为 2 路归并排序


    归并排序是一种较占用内存,效率高,稳定的算法。


    整个排序过程如下图所示:



    算法描述:

    归并操作的工作原理如下:
    第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
    第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
    第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
    重复步骤3直到某一指针超出序列尾
    将另一序列剩下的所有元素直接复制到合并序列尾


    具体代码如下:

    1、排序前的一些准备工作,建立合适的排序需要的结构。

    /********* 排序用到的结构  头文件sort_struct.h ************/
    #include <ctime>
    #include <cstdlib>
    #define MAXSIZE 100 //要排序数组个数最大值
    
    
    class SqList{
    public:
    	int r[MAXSIZE+1];
    	int length;
    };
    
    /* 交换L中数组r下标为i和j的值 */
    void swap(SqList *L, int i, int j)
    {
    	int temp = L->r[i];
    	L->r[i] = L->r[j];
    	L->r[j] = temp;
    }
    
    /* 显示数组内容 */
    void showSqList(SqList *L)
    {
    	for(int i=1;i<=L->length;i++)
    		std::cout<<L->r[i]<<"  ";
    	std::cout<<std::endl;
    }
    
    /* 为数组随机产生一串数字 */
    double random(double start, double end)
    {
        return start+(end-start)*rand()/(RAND_MAX + 1.0);
    }
    void RandomCreat(SqList *L,int len)
    {	
    	double random(double,double);
        srand(unsigned(time(0)));
    	for(int i=1;i<=len;i++)
    	{
    		L->r[i] = int(random(0,100));
    	}
    }

    2、编写主文件,实现排序与测试。

    /********* C++堆排序算法 ************/
    #include<iostream>
    #include<time.h>
    #include<Windows.h>
    #include"sort_struct.h"
    using namespace std;
    
    /* 将有序的SR[i...m]和SR[m+1...n]归并为有序的TR[1...n] */
    void Merge(int SR[],int TR[],int i,int m,int n)
    {
    	int j,k,l;
    	for(j=m+1,k=i;i<=m && j<=n;k++)	//将SR中记录由小到大归并入TR
    	{
    		if(SR[i]<SR[j])
    			TR[k] = SR[i++];
    		else
    			TR[k] = SR[j++];
    	}
    	if(i<=m)
    	{
    		for(l=0;l<=m-i;l++)
    			TR[k+l] = SR[i+l];	//将剩余的SR[i...m]复制到TR
    	}
    	if(j<=n)
    	{
    		for(l=0;l<=n-j;l++)
    			TR[k+l] = SR[j+l];	//将剩余的SR[j...n]复制到TR
    	}
    
    }
    
    /* 将SR[]中相邻长度为s的子序列两两归并到TR[] */
    void MergePass(int SR[],int TR[],int s,int n)
    {
    	int i = 1;
    	int j;
    	while(i<=n-2*s+1)
    	{
    		Merge(SR,TR,i,i+s-1,i+2*s-1);	//两两归并
    		i = i+2*s;
    	}
    	if(i<n-s+1)		//归并最后两个序列
    		Merge(SR,TR,i,i+s-1,n);
    	else			//若最后只剩下单个子序列
    		for(j=i;j<=n;j++)
    			TR[j] = SR[j];
    }
    
    /* 对顺序表L作归并非递归排序 */
    void MergeSort(SqList *L)
    {
    	int *TR = new int[L->length+1];	//申请额外空间
    	int k = 1;
    	while (k<L->length)
    	{
    		MergePass(L->r,TR,k,L->length);
    		k = 2 * k;						//子序列长度加倍
    		MergePass(TR,L->r,k,L->length);
    		k = 2 * k;						//子序列长度加倍
    	}
    	delete[] TR;
    }
    
    int main()
    {
    	SqList *L = new SqList;
    	L->length = 10;
    	RandomCreat(L,L->length);
    	cout<<"排序前:";
    	showSqList(L);
    
    	MergeSort(L);
    	cout<<"归并排序后:";
    	showSqList(L);
    
    	return 0;
    }


    运行结果如下:



  • 相关阅读:
    Python_Openpyxl 浅谈(最全总结 足够初次使用)
    @requestMapping的produces和consumes属性
    JDK、CGLIB、Spring 三种实现代理的区别(三)Spring的ProxyFactory
    SpringBoot实现限制ip访问次数
    springboot过滤器禁止ip频繁访问
    工厂模式,简单工厂模式,抽象工厂模式三者有什么区别
    eclipse中git用本地或线上分支完全覆盖本地分支——reset
    Eclipse 中git插件文件冲突解决
    客名利
    Bootstrap3基础 栅格系统 页面布局随 浏览器大小的变化而变化
  • 原文地址:https://www.cnblogs.com/fengty90/p/3768834.html
Copyright © 2011-2022 走看看