插入排序 Insert sort

Posted 幽流书堂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了插入排序 Insert sort相关的知识,希望对你有一定的参考价值。

曲径通幽,隰有苌楚。夹岸百里,婀娜其实。 每周学习一个算法。

插入排序的排序过程是,将第 i 项和第 i - 1 项比较,如果发生逆序,则交换;再将原第 i 项与第 i - 2 项比较,以此类推,直到找到合适的位置。插入排序当中,每一轮排序结束后,第 0 项至第 i 项都是排好序的,新的一轮排序是给未排序的值在排好的部分当中找到合适的位置插入的过程。


插入排序是稳定的排序算法,平均时间复杂度为 O(n2)。

插入排序的算法很简短,也很好理解。

void insertSort(int list[])
{ int temp, i, j; for (i = 1; i < 20; i++) if (list[i] < list[i - 1])//if reversed { temp = list[i]; j = i - 1; do {//move all of items to right which less than current item in order to give a piece of space for it list[j + 1] = list[j]; j--; } while (j >= 0 && temp < list[j]); list[j + 1] = temp;//put current item to this place }
}

这个算法的每一轮排序结果在稍后介绍,先来探究其效率。由于需要纳秒时钟,所以拿到了 Linux 平台来实现。编写一个测试类:

//Test class for insert sort
//Author: Koan
#include <iostream>
#include <ctime>
#include <iomanip>
using namespace std;

void display(int *list);
void insertSort(int list[]);

int main()
{ int randomlist[20] = { 8,15,7,22,78,45,17,9,15,58,27,81,34,35,61,69,88,1,97,29 }; int nearlysortedlist[20] = { 1,8,7,9,15,17,15,22,27,35,34,29,45,58,69,61,88,97,78,81 }; int reversedlist[20] = { 97,88,81,78,69,61,58,45,35,34,29,27,22,17,15,15,9,8,7,1 }; int fewuniquelist[20] = { 18,5,76,36,5,18,5,36,76,5,76,18,5,76,36,18,76,36,18,36 }; struct timespec begin = {0, 0};//use for counting the time struct timespec end = {0, 0}; cout << "The random list is" << endl; display(randomlist); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &begin); insertSort(randomlist); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end); cout << "It took " << end.tv_nsec - begin.tv_nsec << " ns by insert sort. Result is" << endl; display(randomlist); cout << "The nearly sorted list is" << endl; display(nearlysortedlist); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &begin); insertSort(nearlysortedlist); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end); cout << "It took " << end.tv_nsec - begin.tv_nsec << " ns by insert sort. Result is" << endl; display(nearlysortedlist); cout << "The reversed list is" << endl; display(reversedlist); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &begin); insertSort(reversedlist); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end); cout << "It took " << end.tv_nsec - begin.tv_nsec << " ns by insert sort. Result is" << endl; display(reversedlist); cout << "The list with few unique values is" << endl; display(fewuniquelist); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &begin); insertSort(fewuniquelist); clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end); cout << "It took " << end.tv_nsec - begin.tv_nsec << " ns by insert sort. Result is" << endl; display(fewuniquelist); return 0;
}

void display(int *list)
{ int i; for (i = 0; i < 19; i++) cout << setfill(' ') << setw(2) << list[i] << ", "; cout << list[i] << endl;
}

运行结果:


多(十)次运行取平均值:

random sorted reversed unique
1149 591 1994 1168
987 479 1282 725
2646 1294 3536 2085
1555 715 1517 975
889 569 1622 986
1479 807 2085 1176
811 406 1011 642
1144 730 1910 1198
1439  629 1807 1072
940 471 1174 680
—— —— —— ——
1304 669 1794 1071

插入排序对接近完成排序的数组的排序效率较高,对逆序数组的排序效率较低。


接下来我们分析每轮排序的结果,帮助理解这个排序算法。

图中红色框起来的是比较时发生逆序的两项,可以看出,红框当中的第二个数在下一轮中排在了正确的位置。酸橙色框起来的是没有发生逆序的两个值,算法当中将跳过这一轮循环,继续下一轮比较。

以上是关于插入排序 Insert sort的主要内容,如果未能解决你的问题,请参考以下文章

计数排序(Count Sort )与插入排序(Insert Sort)

插入排序Insertion sort

模板小程序链表排序(qsort/insert_sort/merge_sort)

python排序(插入排序) 从小到大顺序

希尔排序

排序方法补