排序算法总结(数据结构排序算法)

本文详细总结了排序算法,包括插入排序(直接插入、折半插入、希尔排序)、交换排序(冒泡排序、快速排序)、选择排序(简单选择排序、堆排序)、归并排序和基数排序(LSD和MSD)。讨论了各种排序算法的空间复杂度、时间复杂度、稳定性和适用场景,特别指出快速排序在平均情况下的优秀性能,以及外部排序中多路归并、置换选择排序和最佳归并树的概念。
摘要由CSDN通过智能技术生成

最近复习数据结构,看完排序,就想着赶紧总结一下,供自己整理学习,也供大家一起学习进步。

    目    录

一、概述

二、内排序

1.插入排序

1)直接插入排序

         2)折半插入排序(先折半查找再移动插入)

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

2.交换排序

1)冒泡排序

2)快速排序

3.选择排序

1)简单选择排序

2)堆排序

4.归并排序

5.基数排序(桶排序)

1)LSD

2)MSD

三、内部排序总结

四、外部排序

1.置换选择排序

2.最佳归并树

3.败者树

 


一、概述

  1. 排序分为内排序和外排序。衡量算法的三个主要标准,空间复杂度、时间复杂度、稳定性(稳定性指关键字相同的元素,在排序后前后相对顺序不变,本身不含褒贬)。
  2. 内排序又分为插入排序、交换排序、选择排序、归并排序、基数排序(根据算法实现的思想不同)。
  3. 外排序主要采用归并排序,为提高外部排序的效率有三种相关的优化算法。

二、内排序

1.插入排序

插入排序包含:直接插入排序、折半插入排序、希尔排序

1)直接插入排序

算法思想:将数据集合看作是两个部分,前部分是有序集合,后半部分是待排序集合,每次从待排序的集合中取第一个元素,将其插入到有序集合应该放入的位置。在插入时候涉及到向后移位的操作,因为待插入位置之后的元素要向后移动,在直接插入排序中,比较移位同时进行的,待插入元素依次向前比较,若前一个元素大于它,则将前一个元素向后移动,再向前比较下一个元素,如图此时待排序元素为2,2与4比较,2小于4,在4前面,4向后移,2比较3,3向后移,2比较1,2在1后,则插入1之后。

void InsertSort(int array[],int len){
	int i,j,key;
	for(i=1;i<len;i++){
		if(array[i]<array[i-1]){
			key=array[i];
			for(j=i-1;j>=0&&array[j]>key;j--){
				array[j+1]=array[j];
			}
			array[j+1]=key;
		}
		
	}
}

空间复杂度:O(1);

时间复杂度:最好情况,序列已经是升序排列了,需要进行的比较操作需(n-1)次即可。最坏情况,序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。插入排序的赋值操作是比较操作的次数加上 (n-1)次。平均来说插入排序算法的时间复杂度为O(n^2);

稳定性:稳定;

使用范围:适用于顺序存储和链式存储。

总结:排序效率与初始序列的状态有关,适用于初始基本有序且规模不太大的序列,对于初始状态基本无序的序列,时间消耗较大。

2)折半插入排序(先折半查找再移动插入)

算法思想:直接插入排序是边比较边移动(如递增序列,若小于前一个数,前一个数向后移,继续向前比较),而折半插入排序则是将比较移动进行分离。先折半查找元素待插入的位置,再统一移动待插入位置之后的所有元素。因此,折半插入排序主要是减少了元素比较的次数,但移动次数没变。

void BinaryInsertSort(int array[],int len){
	int i,j,low,high,mid,key;
	for(i=1;i<len;i++){
		if(array[i]<array[i-1]){
			key=array[i];
			high=i-1;
			low=0;
			while(low<=high){
				mid=(high+low)/2;
				if(array[mid]>array[i])
					high=mid-1;
				else
					low=mid+1;
			}
			for(j=i;j>low;j--){
				array[j]=array[j-1];
			}
			array[low]=key;
		}
	}
}

空间复杂度:O(1);

时间复杂度:比较次数减小,平均为O(nlog2n),移动次数未减少,平均来说,算法的时间复杂度为O(n^2);

稳定性:稳定;

使用范围:适用于顺序存储。

总结:比较次数与待排序列初始状态无关,移动次数与初始序列状态有关,对于顺序存储的数据,使用折半插入可以节省比较的时间,但总的移动次数没有变。

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

直接插入排序适用于数据量不大的排序,希尔排序适用于数据量比较大的情况。

算法思想:将数据分成若干组,假设a[10]内存有10个无序元素,取增量d为10/2=5,则将10个数据分为5组,每组2个元素,将下标为0,5(0+d)定义为1组,1,6(1+d)定义为2组,3,7(3+d)定义为3组,4,8(4+d)定义为4组,5,9(5+d)定义为5组(注意这里是说的下标),然后每组中的元素进行比较,如不符合排序规则就进行插入排序操作。

假设a[10]={8,5,3,1,2,4,6,9,7,0},递增排序;

第一轮增量为5,分组如下:

8,4为一组,4在8前,插入排序,4插入8前,则相当于两数互换,4,8;

5,6为一组,5在6前,插入排序,位置不变;

3,9为一组,3在9前,插入排序,位置不变;

1,7为一组,1在7前,插入排序,位置不变;

2,0为一组,0在2前,插入排序,0插入2前,相当于两数互换,0,2;

第二轮,取增量为d=5/2=2(此时5为第一次取的增量),分成2组,每组5个元素,下标0,2(0+d),4(0+2d),6(0+3d),8(0+4d)为第一组,下标1,3(1+d),5(1+2d),7(1+3d),9(1+4d)为第二组,分组情况如图。

此时执行插入排序,即{4,3,0,6,7}和{5,1,8,9,2}分别执行直接插入排序,直接插入排序过程就不赘述了(依次向前比较),比较结果插入相应位置,结果为{0,3,4,6,7}和{1,2,5,8,9},此时排序情况如图。

第三轮,取增量为d=2/2=1(2为第二轮所取的增量),分成1组,即全部10个元素执行直接插入排序,此时,因为元素经过上面两轮的排序,已经具有较好的局部有序性,则很快就能得到最终结果,直接插入排序不做赘述。

void ShellSort(int a[],int len){
	int i,j,d=len/2,k
  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值