• 各种排序


    插入排序算法

    插入排序是最简单的排序算法。插入排序有N-1趟排序组成。对于P=1趟到P=N-1趟,插入排序保证从位置0到位置P上的元素已为排序状态。插入排序利用了这样的事实:位置0到位置P-1上的元素是排过序的。图1显示一个简单的数组在每一趟排序后的情况。

    图1:每趟后的插入排序

    如下代码实现了上述想法:

     

    void InsertionSort(ElementType A[], int N)
    {
    	int j, p;
    	ElementType Tmp;
    	for (p = 1; p < N; ++p){
    		Tmp = A[p];
    		for (j = p; A[j - 1] > Tmp && j > 0; --j){
    			A[j] = A[j - 1];
    		}
    		A[j] = Tmp;
    	}
    }

    在第2行到第5行实现数据移动而没有明显使用交换。位置P上的元素存于Tmp,而在位置P之前所有更大的元素都被向右移动一个位置。然后Tmp被置于正确的位置上。

    从代码中可以看出,插入排序复杂度是O(N^2),但如果输入数据已预先排序,那么运行时间为O(N)。

    希尔排序

    通过比较相距一定间隔的元素来工作,各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止。所以希尔排序也叫缩小增量排序。希尔排序使用一个序列h1,h2,....,hn,叫做增量序列,只要h1=1,任何增量序列都是可以的,不过有些增量序列比另外一些增量序列更好。在使用增量hk的一趟排序后,对于每一个i,我们有A[i] <= A[i+hk],即所有相隔hk的元素都被排序,此时和排序文件是hk-排序的。希尔排序的一个重要性质是:一个hk-排序的文件保持它的hk-排序性。如果情况不是这样的话,希尔排序也就没有意义了。

    hk-排序的一般做法是:对于hk,hk+1,...,N-1中的每一个位置i,把其上的元素放到i,i-hk,i-2*hk....中间的正确位置上。一趟hk排序的作用就是对hk个独立的子数组执行一次插入排序。

    希尔排序的运行时间依赖于增量序列,但最坏情形下的运行时间为O(N^2),但对于有些增量序列,其时间可减少到O(N^1.2)。以下是以增量序列:1,2,4,N/2的一种实现:

    void Shellsort(ElementType A[], int N)
    {
    	int i, j, Increment;
    	ElementType Tmp;
    
    	for (Increment = N / 2; Increment > 0; Increment /= 2){
    		for (i = Increment; i < N; ++i){
    			Tmp = A[i];
    			for (j = i; j >= Increment; j -= Increment){
    				if(Tmp < A[j-Increment])
    					A[j] = A[j - Increment];
    				else
    					break;
    			}
    			A[j] = Tmp;
    		}
    	}
    }

    堆排序

    堆排序主要是从二叉堆中通过删除最小元(树根)而得。回忆一下,建立N个元素的堆,需要线性O(N)的时间,然后执行N次DeleteMin操作。按照顺序,最小的元素先离开该堆。通过将这些元素离开的顺序即可得到N个元素的排序,因此总的时间复杂度是O(NlogN)。经验指出,堆排序是一个非常稳定的算法,它平均使用的比较只比最坏情形界指出的略少。执行堆排序的代码如下:

    #define LeftChild(i) (2 * (i) + 1)
    
    void PercDown(ElementType A[], int i, int N)
    {
    	int child;
    	ElementType Tmp;
    
    	for (Tmp = A[i]; LeftChild(i) < N; i = child){
    		child = LeftChild(i);
    		if (child != N - 1 && A[child + 1] > A[child])
    			++child;				//找到最大的儿子节点
    		if (Tmp < A[child])
    			A[i] = A[child];
    		else
    			break;
    	}
    	A[i] = Tmp;
    }
    
    void HeapSort(ElementType A[], int N)
    {
    	int i;
    	for (i = N / 2; i >= 0; --i)
    		PercDown(A, i, N);			//构造堆
    	for (i = N -1; i > 0; --i){
    		Swap(&A[0], &A[i]);			//将最大元素(根)与数组末尾元素交换,从而删除最大元素,重新构造堆
    		PercDown(A, 0, i);
    	}
    }



  • 相关阅读:
    XML Schema (1)
    xml
    java输入输出流(内容练习)
    Java中I/O的分析
    java File类
    java中Map的用法(HaspMap用法)
    Git
    oracle安装分析
    博客第一天
    正则化 L1 L2
  • 原文地址:https://www.cnblogs.com/aukle/p/3225865.html
Copyright © 2020-2023  润新知