排序之直接插入排序

直接插入排序

扑克牌是我们几乎每个人都可能玩过的游戏。最基本的扑克玩法都是一边摸牌,一边理牌。假如我们拿到了这样一手牌,如图所示。啊,似乎是同花顺呀,别急,我们得理一理顺序才知道是否是真的同花顺。请问,如果是你,应该如何理牌呢?

在这里插入图片描述

将 3 和 4 移动到 5 的左侧,再将 2 移动到最左侧,顺序就算是理好了。这里,我们的理牌方法,就是直接插入排序法。

1.直接插入排序算法

直接插入排序(Straight Insertion Sort)的基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增 1 的有序表。

从名称上可以知道它是一种插入排序的方法。来看直接插入排序法的代码:

/* 对顺序表 L 作直接插入排序 */
void InsertSort(SqList *L) {
	int i, j;
	for (i = 2; i <= L->length; i++) {
		/* 需将 L->r[i] 插入有序子表 */
		if (L->r[i] < L->r[i-1]) {
			/* 设置哨兵 */
			L->r[0] = L->[i];
			for (j = i - 1; L->r[j] > L->r[0]; j--) {  
				/* 记录后移 */	
				L->[j+1] = L->[j];
			}
			L->r[j+1] = L->r[0];
		}
	}
}

步骤详解:

a. 程序开始运行,此时我们传入的SqList参数的值为length=6,r[6]={0,5,3,4,6,2},其中r[0]=0将用于后面起到哨兵的作用。

b. 外层 for 是排序的主循环。i 从 2 开始的意思是我们假设 r[1]=5 已经放好位置,后面的牌其实就是插入到它的左侧还是右侧的问题。

c. 开始,此时 i=2,L.r[i]=3 比 L.r[i-1]=5 要小,因此执行 if 下的操作。我们将L.r[0]赋值为 L.r[i]=3 的目的是为了起到内层 for 的循环终止的判断依据。如下图所示。图中下方的虚线箭头,就是 L.r[j+1]=L.r[j]的过程,将5右移一位。

在这里插入图片描述

d. 此时,扑克数字 5 在移动完成后,空出了空位,然后 L.r[j+1]=L.r[0],将哨兵的 3 赋值给 j=0 时的L.r[j+1],也就是说,将扑克牌 3 放置到 L.r[1] 的位置,如下图所示:

在这里插入图片描述

e. 继续外层循环,因为此时 i=3,L.r[i]=4 比 L.r[i-1]=5 要小,因此执行 if 后的操作,将5再右移一位,将4放置到当前5所在位置,如下图所示:

在这里插入图片描述

f. 再次外层循环,此时 i=4。因为 L.r[i]=6 比 L.r[i-1]=5 要大,于是 if 后代码不执行,此时前三张牌的位置没有变化,如下图所示:

在这里插入图片描述

g. 再次外层循环,此时 i=5,因为 L.r[i]=2 比 L.r[i-1]=6 要小,因此执行 if 后的操作。由于 6、5、4、3都比 2 小,它们都将右移一位,将 2 放置到当前 3 所在位置。如下图所示,此时我们的排序也就完成了:

在这里插入图片描述

2.直接插入排序复杂度分析

我们来分析一下这个算法,从空间上来看,它只需要一个记录的辅助空间,因此关键是看它的时间复杂度。

当最好的情况,也就是要排序的表本身就是有序的,比如纸牌拿到后就是{2,3,4,5,6},那么我们比较次数,其实就是代码第 6 行每个 L.r[i] 与 L.r[i-1] 的比较,共比较了 (n-1)sigma(i=2, n, 1) 次,由于每次都是 L.r[i]>L.r[i-1],因此没有移动的记录,时间复杂度为 O(n)。

当最坏的情况,即待排序表是逆序的情况,比如 {6,5,4,3,2},此时需要比较 sigma(i=2, n, i)=2+3+…+n=(n+2)(n-1)/2次,而记录的移动次数也达到最大值 sigma(i=2, n, i+1)=(n+4)(n-1)/2次。

如果排序记录是随机的,那么根据概率相同的原则,平均比较和移动次数约为 n2/4 次。因此,我们得出直接插入排序法的时间复杂度为 O(n2)。从这里也看出,同样的 O(n2) 时间复杂度,直接插入排序法比冒泡和简单选择排序的性能要好一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值