插入排序 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)