zoukankan      html  css  js  c++  java
  • 算法之旅——合并排序

    合并排序是用分治策略实现对n 个元素进行排序的算法。其基本思想是,将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集合合并成所要求的排好序的集合。

    其递归描述如下:

    #include <iostream>
    #define N 8
    typedef int Type;
    using namespace::std;
    
    Type *b = new Type[N];
    
    void MergeSort(Type a[], int left, int right);
    void Merge(Type a[], Type b[], int left, int i, int right );
    
    void MergeSort(Type a[], int left, int right)
    {
    	if(left < right)
    	{
    		int i = (left + right) / 2;
    		MergeSort(a, left, i);
    		MergeSort(a, i+1, right);
    		Merge(a, b, left,  i, right);  //Merge to array of 'b'
    	}
    }
    
    void Merge(Type a[], Type b[], int left, int i, int right )
    {
    	int x = left, y = i+1, k = left;
    	while((x <= i) && (y <= right))
    	{
    		if(a[x] < a[y])  b[k++] = a[x++];
    		else b[k++] = a[y++];
    	}
    	while(x <= i) b[k++] = a[x++];
    	while(y <= right) b[k++] = a[y++];
    
    	for(int i = left; i < k; i++)
    		a[i] = b[i];
    }
    int main()
    {
    	Type a[N] = {4,8,3,7,1,5,6,2};
    	MergeSort(a, 0, 7);
    	for(int i = 0; i < N; i++)
    		cout << a[i] << ',';
    	cout << endl;
    
    	return 1;
    }


    消去递归的合并算法如下:

    #include <iostream>
    typedef int Type;
    
    using namespace::std;
    
    void Merge(Type c[], Type d[], int l, int m, int r)
    {
    	int i = l, j = m+1, k = l;
    	while((i <= m) && (j <= r))
    	{
    		if(c[i] <= c[j]) d[k++] = c[i++];
    		else d[k++] = c[j++];
    	}
    	if(i > m) for(int q = j; q <= r;  q++) d[k++] = c[q];
    	else for(int q = i; q <= m; q++) d[k++] = c[q];
    }
    
    void MergePass(Type x[], Type y[], int s, int n)
    {
    	int i = 0;
    	while( i <= n - 2 * s)
    	{
    		Merge(x, y, i, i+s-1, i+2*s-1);
    		i = i+2 * s;
    	}
    	if(i + s < n) Merge(x, y, i, i+s-1, n-1);
    	else for(int j = i; j <= n-1; j++) y[j] = x[j];
    }
    
    void MergeSort(Type a[], int n)
    {
    	Type *b = new Type[n];
    	int s = 1;
    	int i = 0;
    	while(s < n)
    	{
    		MergePass(a,b,s,n); //合并到数组b
    		s += s;	
    		MergePass(b,a,s,n); // 合并到数组a	
    		s += s;
    	}
    }
    
    int main()
    {
    	Type num[] = {8,4,7,3,1,5,6,2};
    	MergeSort(num, 8);
    	for(int j = 0; j < 8;  j++)
    		cout << num[j];
    	int i; 
    	cin >> i;
    	return 1;
    }


    自然合并排序如下:

    #include <iostream>
    #define N 8
    typedef int Type ;
    using namespace::std;
    
    void MergeSort_Natural(Type a[], int n);
    int Scan(Type a[], Type b[], int n);
    void Merge(Type a[], Type b[], int left , int mid, int right);
    
    //自然归并排序
    void MergeSort_Natural(Type a[], int n)
    {
    	Type *b = new Type[N];
    
    	while(1)
    	{
    		if(Scan(a,b,n) == 0) break;
    		if(Scan(b,a,n) == 0) break;
    	}
    }
    
    /* 线性扫描数列,如果存在逆序的情况就进行合并排序
       否则返回一个为零的中间值mid   
       */ 
    int Scan(Type a[], Type b[], int n)
    {
    	int left = 0, mid = 0, right = n-1;
    	for(int i = 0; i < n-1; i++)
    	{
    		// 判断有没有逆序的情况出现 
    		if(a[i] > a[i+1]){
    			// 先设置中间值,后设置右值
    			if(mid == 0)  mid = i;
    			else {
    				right = i;
    				Merge(a, b, left , mid, right);
    				left = right+1;
    				mid = 0;	
    				right = n-1;
    			}
    		}		
    	}
      // 当最后一个组为最后一个数的极端情况
    	if((mid !=0) && (right != 0))
    		Merge(a, b, left , mid, right);	
    	return mid;
    }
    
    void Merge(Type a[], Type b[], int left , int mid, int right)
    {
    	int i = left, j = mid+1, k = left;
    	while((i <= mid) && (j <= right))
    	{
    		if(a[i] < a[j]) b[k++] = a[i++];
    		else b[k++] = a[j++];
    	}
    	while(i <= mid) b[k++] = a[i++];
    	while(j <= right) b[k++] = a[j++];
    }
    
    int main()
    {
    	Type a[N] = {4,8,3,7,1,5,6,2};
    
    	MergeSort_Natural(a, 8);
    
    	for(int i = 0; i < N; i++)
    		cout << a[i] << ',';
    	cout << endl;
    
    //	int i;
    //	cin >> i;
    	return 1;
    }


    合并排序的一个弊端就是额外需要存储器的空间配置,在实际上的实现上,会极度影响速度和高速缓存的性能!

  • 相关阅读:
    Hive中频繁报警的问题
    Hadoop中Namenode的HA查询和切换
    昨天面试遇到的一道C语言题
    【转】MapReduce的优化
    关于linux修改max user processes limits的问题
    Hadoop-2.6.0安装文档
    C#使用RabbitMQ
    windows配置Erlang环境
    【转】linux查看及修改文件权限以及相关
    (转)C#图解—PictureBox.SizeMode 属性
  • 原文地址:https://www.cnblogs.com/pangblog/p/3367599.html
Copyright © 2011-2022 走看看