简单排序(冒泡、插入、选择)

本文介绍了四种经典的排序算法:冒泡排序、插入排序、希尔排序和选择排序。冒泡排序和插入排序是基础排序算法,时间复杂度在最好和最坏情况下均为O(N^2)。希尔排序通过增量序列改进了交换效率,而选择排序则寻找最小元素交换。这些算法在理解排序原理和优化策略上有重要意义。
摘要由CSDN通过智能技术生成

1. 冒泡排序 Bubble_Sort

假定有一组序列:12 32 9 89 12 21
需要将其排成非递减的序列, 执行一趟排序的操作是:
从头到尾扫描一遍, 发现第i个元素比第i-1个元素大, 则交换两个元素。执行一趟之后,最大的元素必将排到最后。
剩下的N-1个元素,重复执行排序。

算法1.1 原始冒泡排序
void Bubble_Sort( ElementType A[], int N )
{
	for ( p=N-1; P>=0; P-- )
	{
		for ( i=0; i<P; i++ ) /* 一趟排序 */
		{
			if ( A[i] > A[i+1] )
			{
				Swap(A[i], A[i+1]);
			}
		}
	}
}
算法1.2 改良的冒泡排序
void Bubble_Sort( ElementType A[], int N )
{
	for ( p=N-1; P>=0; P-- )
	{
		flag = 0;
		for ( i=0; i<P; i++ ) /* 一趟排序 */
		{
			if ( A[i] > A[i+1] )
			{
				Swap(A[i], A[i+1]);
				flag = 1; /* 标识发生了交换 */
			}
		}
		if ( flag==0 ) break; /*全程无交换, 不需要继续排序*/
	}
}

最好情况:T = O(N)
最坏情况:T = O(N^2)
优势:(1)简单 (2)对数组和链表都容易操作

2. 插入排序 Insertion_Sort

假设要将一个序列排序成非递减的顺序

算法2.1 直接插入排序
void Insertion_Sort( ElementType A[], int N )
{
	for ( P=1; P<N; P++ )
	{
		Tmp = A[P]; /*取出一个元素*/
		for ( i=P; i>0 && A[i-1]>Tmp; i-- )
			A[i] = A[i-1]; /*元素后移*/
		A[i] = Tmp; /*元素落位*/
	}
}

最好情况: T = O(N)    即上届是N级别, O表示上届, Ω表示下届, Θ表示即是上届又是下届
最坏情况: T = O(N^2)

定理2.1:任意N个不同元素组成的序列平均具有N(N-1)/4个逆序对

冒泡排序与插入排序的相同点:
(1) 只对相邻的两个元素交换操作
(2) 一趟排序只能消除一个逆序对
(3) 平均时间复杂度与逆序对的个数有关, 平均时间复杂度Ω(N^2),即下届就是N平方级别的

定理2.2:任何以交换相邻两个元素来排序的算法,其平均时间复杂度为Ω(N^2)
这就意味着,要提高算法效率,必须做到:
(1) 每次消去不止1个逆序对
(2) 每次交换像个较远的2个元素

3. 希尔排序 Shell_Sort

基本思路:利用插入排序的简单,克服插入排序每次只交换相邻元素的缺点.
步骤:
(1) 定义增量序列 Dm > Dm-1 > ... > D1=1
(2) 对每个Dk进行 Dk-间隔 排序(k = m, m-1, ..., 1)
规律: Dk-间隔 有序的序列, 在执行 Dk-间隔 排序后, 任然是 Dk-间隔 有序的

算法3.1 原始希尔排序
增量 Dm = ∟N/2」, Dk = ∟Dk-1/2」,即每次取N/2作为增量
void Shell_Sort( ElementType A[], int N )
{
	for ( D=N/2; D>0; D/2 ) /*希尔排序增量序列*/
	{
		for ( P=D; P<N; P++ ) /*插入排序*/
		{
			Tmp = A[P];
			for ( i=P; i>=D && A[i-D]>Tmp; i-=D )
				A[i] = A[i-D];
			A[i] = Tmp;
		}
	}
}

最坏情况: T = Θ(N^2)
问题在于: 增量序列不互质, 所以要提高效率就在于增量的取值
更多的增量序列
(1) Hibbard增量序列
-> Dk = 2^k - 1 保证相邻元素互质
-> 最坏情况: T = Θ(N^3/2)
-> 猜想的平均复杂度: T = O(N^5/4)
(2) Sedgewick增量序列
-> {1, 5, 19, 41, 109, ...}
  计算公式 9X4^i - 9X2^i + 1  或者 4^i - 3X2^i + 1
-> 猜想: 平均 T = O(N^7/6), 最坏 T = O(N^4/3)

4. 选择排序

基本思路:从i到N-1的序列中找到最小的元素,然后与第i个元素交换

算法4.1 简单选择排序
void Selection_Sort( ElementType A[], int N )
{
	/*从A[i]到A[N-1]中找到最小元素的下标并返回*/
	MinPosition = ScanForMin( A, i, N-1 );
	/*将未排序部分的最小元素换到有序部分的最后位置*/
	Swap( A[i], A[MinPosition] );
}

简单选择排序的时间复杂度 T = Θ(N^2), 关键在于 ScanForMin 函数实现.
如何找到最小元素: 最小堆! --> 堆排序
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值