本文共 1941 字,大约阅读时间需要 6 分钟。
时间复杂度:O(n²)
稳定性:稳定,因为每次插入都是从后向前,所以不会发生相对位置改变。
这个排序算法相较于前面两种算法要难实现一些。
看了很多网上的代码,但是感觉可读性不是很强,于是决定自己动手写一个属于自己的版本。
先讲思想:
对于N个元素,
我们分成三组:
第一组:待插入序列
第二组:待插元素
第三组:剩余元素组
举个栗子
现在有这样一组数:
4,3,2,1
由于第一个元素自己为一组,
所以我们可以从第二个元素开始,看成第一趟插入排序。
那么第一趟插入排序的三个组的组员分别是:
待插入序列:4,*3
其中,*3是一个空格子,只是目前存放了3这个数。
空格子里的数是无意义的,可以被占位,
也是为后面挪格子做准备。
待插元素:3
由于前面的待插元素会被占位,有丢失的风险,
所以我们建立一个临时变量temp来存放待插元素。
剩余元素组:2,1
这个没什么好说的,就是还未参与排序的元素。
现在开始进行插入:
首先,外层一定是一个for循环,
因为要进行N-1次插入,
而第一个将要插入的元素的下标为1,
所以外层我们可以这样写:
进入第一趟插入排序后,
要做的就是让待插元素,依次从后往前地和待插入序列中的元素进行比较,
然后进行挪位置,空出一个位置给待插元素。
为什么可以挪位置?
因为我们的待插入序列中有一个空格子。
那么什么时候算完呢?
当这个待插元素 不再比 待插入序列中下一个要进行比较的元素 小的时候,
或者此时待插元素已经是第一个元素时,
就可以结束本次挪位置,
然后把temp赋给空出的那个位置即可。
也就是说,
函数出口是:
1、待插元素 不再比 待插入序列中下一个要进行比较的元素 小
2、待插元素已经是第一个元素
这里我使用了while循环。
先定义一个j = i,
让while(j),
那么j可操纵的值为0,1,也就是两次。
那么第一趟插入排序
会将temp和4进行比较,
4的数组下标是0,也就是j-1,
所以比较的代码是:
if (temp < array[j - 1]) { array[j] = array[j - 1]; j--; cout << "这是第" << i << "趟排序中的第"<<<"次挪位" << endl; }
很显然,3比4小,
所以我们将a[1]的值变为4,
现在a[0]就空出来了。
此时j为0。
j为0的时候,
也就意味着3将要和a[-1]进行比较,当然没有这个元素,
也就是说,此时3为待插入序列中的第一个元素了。
所以结束本次内层while循环。
另一种结束本次内层循环的语句是:
while (j) { if (temp < array[j - 1]) { array[j] = array[j - 1]; j--; num++; cout << "这是第" << i << "趟排序中的第"<<<"次挪位" << endl; } else { break; } }
此时来到第一层外层循环,
我们在尾部写:
array[j] = temp;
即可。
然后函数将不断地进行上述判断,
直至所有序列排序完毕,
插入排序结束。
代码:
templatevoid myInsertSort(T array[], int len){ for (int i = 1; i < len; i++) { int j = i; T temp = array[i]; int num = 0; while (j) { if (temp < array[j - 1]) { array[j] = array[j - 1]; j--; num++; cout << "这是第" << i << "趟排序中的第"< <<"次挪位" << endl; } else { break; } } array[j] = temp; cout << "这是第" << i << "趟排序" << endl; }}
测试代码:
int a[] = { 2,6,8,4,7,10,1 }; int len = sizeof(a) / sizeof(a[0]); myInsertSort(a, len); for (int i = 0; i < len; i++) { cout << a[i] << endl; }
运行截图:
转载地址:http://klzz.baihongyu.com/