• 11、排序【理论篇】


    排序

    一、基本概念:

    1、排序:就是将一组杂乱无章的数据按一定的规律排列起来

    2、内部排序和外部排序:

    • 整个排序过程完全在内存中进行——内部排序
    • 数据量较大需要借助外部存储设备才能完成——外部排序

    二、插入类排序:

    (一) 思想:每步将一个待排序的对象,按其关键码大小,插入到前面已经排好序的一组对象适当位置上,直到对象全部插入为止

    (二) 分类:

    1、直接插入排序:

    ①  思想:最基本的插入排序,将将第i个插入到前i-1个中的适当位置      

    ②  时间复杂度:T(n) = O(n²)

    ③  空间复杂度:S(n) = O(1)

    ④  稳定性:是一种稳定的排序,时间复杂度最坏的情况是数据已经有序,时间复杂度最好的情况是数据完全逆序

    ⑤  程序代码:

    #include"stdio.h"
    #define N 8
    int main()
    {
        int i, j, m, temp;
        int a[N];
        for(i = 0; i < N; i++)
        {
            printf("please input a number :" );
            scanf("%d",&m);
            a[i] = m;
        }
     
        printf("The old array is: ");
        printf("
    ");
        for(i = 0; i < N; i++)
        {
            printf("%d	",a[i] );
        }
        printf("
    " );
    
    	for(i = 1; i < N; i++)
    	{
    		for(j = 0; j < i; j++ )
    		{
    			if(a[j] < a[i])
    			{		
    				temp = a[j];
    				a[j] = a[i];
    				a[i] = temp;
    				i = j;
    			}
    
    		}
    		
    	}
    
        printf("The new array is: ");
        printf("
    ");
        for(i = 0; i < N; i++)
        {
            printf("%d	",a[i] );
        }
        printf("
    " );
         
        return 0;
    }
    
     
    2、  折半插入排序(二分排序):

    ①  思想:因为是已经确定了前部分是有序序列,所以在查找插入位置的时候可以用折半查找的方法进行查找,提高效率。

    ②  时间复杂度:比较时的时间减为O(n㏒n),但是移动元素的时间耗费未变,所以总是得时间复杂度还是O(n²)。

    ③  空间复杂度:S(n) = O(1)。

    ④     稳定性:是一种稳定的排序

    ⑤     程序代码:

    void BInsertSort(int L[])
    { 
    	int i,j,high,low,mid; 
    	for(i=2;i<=n;i++)
    	{ 
    		L[0] = L[i];        		//待排序的数进监视哨
    		low=1;
    		high=i-1;     			//初始化low,high
    		while(low<=high)    		//循环语句确定插入位置,必须保证low<high
    		{ 
    			mid=(low+high)/2; 
    			if(L[0]<L[mid])     	//根据L[0]的值的大小,确定属于低半区还是高半区
    				high=mid-1;     //插入低半区
    			else low=mid+1;     	//插入高半区
    		} 
    		for(j=i-1;j>=high+1;j--)	//待插入位置后面全部数后移一位
    			L[j+1]=L[j];    
    		L[high+1]=L[0];      		//监视哨里面的数插入数列
    	} 
    }
    

       

    3、  希尔排序(缩小增量排序):

    ①  思想:把待排序序列分成若干较小的子序列,然后逐个使用直接插入排序法排序,最后再对一个较为有序的序列进行一次排序,主要是为了减少移动的次数,提高效率。

    ②  时间复杂度:O(n的1.5次方)

    ③  空间复杂度:S(n) = O(1)。

    ④  稳定性:是一种不稳定排序

    三、交换类排序:

    (一) 思想:是在待排序的记录序列中,两两比较待排序记录关键字,并交换不满足要求的偶对,直到整个序列中所有记录都满足要求为止。

    (二) 分类:

    1、  冒泡排序:

    ① 思想:反复扫描待排序序列,在扫描的过程中顺次比较相邻的两个元素的大小,若逆序就交换位置。第一趟,从第一个数据开始,比较相邻的两个数据,(以升序为例)如果大

    就交换,得到一个最大数据在末尾;然后进行第二趟,只扫描前n-1个元素,得到次大的放在倒数第二位。以此类推,最后得到升序序列。如果在扫描过程中,发现没有交换,说明

    已经排好序列,直接终止扫描。所以最多进行n-1趟扫描。

    ② 时间复杂度:T(n) = O(n²)

    ③ 空间复杂度:S(n) = O(1)

    ④ 稳定性:是一种稳定的排序,时间复杂度最好的情况是数据已经有序,时间复杂度最坏的情况是数据完全逆序

    ⑤   程序代码:

    #include"stdio.h"
    #define N 8
    int main()
    {
    	int a[N];
    	int i, j, m, temp;
    
    	for(i = 0; i < N; i++)
    	{
    		printf("please input a number :" );
    		scanf("%d",&m);
    		a[i] = m;
    	}
    
    	for(i = 0; i < N; i++)
    	{	for(j = 0; (j < N - i)&&(j+1 < N - i); j++)
    		{
    			if(a[j]< a[j+1])
    			{
    				temp = a[j];
    				a[j] = a[j+1];
    				a[j+1] = temp;	
    			}
    		}
    	}
    
    	printf("The new array is : ");
    	printf("
    ");
    	for(i = 0; i < N; i++)
    	{
    		printf("%d	",a[i]);	
    	}
    	printf("
    " );	
    	return 0;
    }  
     
    2、  快速排序:

    ①   思想:冒泡排序一次只能消除一个逆序,为了能一次消除多个逆序,采用快速排序。以一个关键字为轴,从左从右依次与其进行对比,然后交换,第一趟结束后,可以把序列分

    为两个子序列,然后再分段进行快速排序,达到高效。

    ②   时间复杂度:平均T(n) = O(n㏒n),最坏O(n²)。

    ③   空间复杂度:S(n) = O(㏒n)。

    ④   稳定性:不稳定排序。

    四、选择类排序:

    (一) 思想:每一趟在n – i + 1 ( i = 1,2, … , n - 1)个记录中选取关键字最小的记录作为有序序列中的第i个记录。

    (二) 分类:

    1、  简单选择排序:

    ① 思想:第一趟时,从第一个记录开始,通过n – 1次关键字的比较,从n个记录中选出关键字最小的记录,并和第一个记录进行交换。第二趟从第二个记录开始,选择最小的和第

    二个记录交换。以此类推,直至全部排序完毕。

    ② 时间复杂度:T(n) = O(n²)。

    ③ 空间复杂度:S(n) = O(1)。

    ④   稳定性:是一种不稳定排序

    ⑤ 程序代码:

    #include"stdio.h"
    #define N 8
    int main()
    {
    	int i, j, m, temp;
    	int a[N];
    
    	for(i = 0; i < N; i++)
    	{
    		printf("please input a number :" );
    		scanf("%d",&m);
    		a[i] = m;
    	}
    
    	for(i = 0;i < N; i++)
    	{	for(j = i+1; j < N; j++)
    		{
    			if(a[i] < a[j])
    			{
    				temp = a[i];
    				a[i] = a[j];
    				a[j] = temp;
    			}
    		}
    	}
    
    	printf("The new array is: ");
    	printf("
    ");
    	for(i = 0; i < N; i++)
    	{
    		printf("%d	",a[i] );
    	}
    	printf("
    " );
    	
    	return 0;
    }  
     
    2、堆排序:

    ① 思想:把待排序记录的关键字存放在数组r[1…n]中,将r看成是一刻完全二叉树的顺序表示,每个节点表示一个记录,第一个记录r[1]作为二叉树的根,一下个记录r[2…n]依次逐

    层从左到右顺序排列,任意节点r[i]的左孩子是r[2i],右孩子是r[2i+1],双亲是r[i/2向下取整]。然后对这棵完全二叉树进行调整建堆。

    ② 时间复杂度:T(n) = O(n㏒n)

    ③ 空间复杂度:S(n) = O(1)

    ④ 稳定性:是一种不稳定排序 

     

    五、归并排序:

    1、  归并排序:

    ① 思想:假设初始序列右n个记录,首先将这n个记录看成n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2向上取整 个长度为2(n为奇数时,最后一个序列的长

    度为1)的有序子序列。在此基础上,在对长度为2的有序子序列进行两两归并,得到若干个长度为4的有序子序列。如此重复,直至得到一个长度为n的有序序列为止。

    ② 时间复杂度:T(n) = O(n㏒n)。

    ③ 空间复杂度:S(n) = O(n)。

    ④ 稳定性:是一种稳定排序

     

    六、总结:

    (1)简单排序法一般只用于n较小的情况(例如n<30)。当序列的记录“基本有序”时,直接插入排序是最佳的排序方法。如果记录中的数据较多,则应采用移动次数较少的简单选择排序法。

    (2)快速排序、堆排序和归并排序的平均时间复杂度均为O(n㏒n),但实验结果表明,就平均时间性能而言,快速排序是所有排序方法中最好的。遗憾的是,快速排序在最坏情况下

    的时间性能为O(n²)。堆排序和归并排序的最坏时间复杂度仍为O(n㏒n),当n较大时,归并排序的时间性能优于堆排序,但它所需的辅助空间最多。

    (3)可以将简单排序法与性能较好的排序方法结合使用。例如,在快速排序中,当划分子区间的长度小于某值时,可以转而调用直接插入排序法;或者先将待排序序列划分成若干

    子序列,分别进行直接插入排序,然后再利用归并排序法,将有序子序列合并成一个完整的有序序列。

    (4)从排序的稳定性上来看,在所有简单排序法中,简单选择排序是不稳定的,其他各种简单排序法都是稳定的。然而,在那些时间性能较好的排序方法中,希尔排序、快速排

    序、堆排序都是不稳定的,只有归并排序、基数排序是稳定的。

    七、排序算法比较:

    1、排序类别

    2、优劣性

    3、最优排序总结 

    (1)序列完全有序,或者序列只有尾部部分无序,且无序数据都是比较大的值时,【直接插入排序】最佳(哪怕数据量巨大,这种情形下也比其他任何算法快)

    (2)数据基本有序,只有少量的无序数据零散分布在序列中时,【希尔排序】最佳

    (3)数据基本逆序,或者完全逆序时, 【希尔排序】最佳(哪怕是数据量巨大,希尔排序处理逆序数列,始终是最好的,当然三数取中优化的快速排序也工作良好)

    (4)数据包含大量重复值,【希尔排序】最佳(来自实验测试,直接插入排序也表现得很好)

    (5)数据量比较大或者巨大,单线程排序,且较小几率出现基本有序和基本逆序时,【快速排序】最佳

    (6)数据量巨大,单线程排序,且需要保证最坏情形下也工作良好,【堆排序】最佳

    (7)数据量巨大,可多线程排序,不在乎空间复杂度时,【归并排序】最佳

  • 相关阅读:
    HDU 6043
    HDU 6033
    HDU 6041
    HDU 6050
    HDU 6053
    HDU 6055
    HDU 6045
    HDU 6044
    HDU 6040
    ZUFE 1035 字符宽度编码(字符串)
  • 原文地址:https://www.cnblogs.com/wxt19941024/p/6899451.html
Copyright © 2020-2023  润新知