插入排序的基本思想是:每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。
插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,
下面直接看C代码的实现:
void insertSort( int num[], int count )
{
int i, j;
for( i = 1; i < count; i++ )
{
if( num[i] < num[i - 1] )
{
int temp = num[i];
for( j = i; j > 0; j-- ) //num[i] 前面的每一个数字和num[i]比较
{
if( num[j - 1] > temp ) //如果num[i]前面的值比num[i]大
{
num[j] = num[j - 1];//将大的值向后挪一位
}
else
{
break;
}
}
num[j] = temp; //将num[i]位置的值放到最后一次挪位置的地方
} //也就是将比num[i]大的值依次向后挪一位,将num[i]直接放到前面
}
}
从数组第二个元素开始,依次和前面的元素比较,如果前面的元素大于当前元素,就将大元素移动到数组后面,小的元素移动到数据前面。
下面逐步分析一下程序运行过程。
首先用数组第二个数8和前一个数字0比较,8>0,不需要交换。下来用数组第三个数字1和前面的8比较,8>1,要移动位置,于是先将1保存起来,然后将数组第三个数字写成8,下来准备将1放到数组第二个位置,但是放之前还需要继续和前一个数字比较,以免刚把1放到第二个位置后,前面的数字还是比1大,又要继续移动1的位置。为了减少移动次数,在放数字之前先和前面数比较,如果前面已经没有比1大的数字后,才将1放到固定位置。此时数组中第二个和第三个数都是8,1被存在临时位置。
下来用1继续和前面的数字0比较,0<1,所以数字1不需要继续向前移动,将1放在数组第二个位置。
接下来用数组第三个数8和前面的数字依次比较,前面的数比8小,不需要移动。
下来继续用数组第四个数5和前面的数字比较。
5和前面的8比较,8>5,需要移动5的位置,先将5存到到临时位置,将5的位置写成8,下来继续用5和前面的数据依次比较,前面的数据都比5小,所以将5放到数组中第三个位置。
下来接在用数组中第五个数4依次和前面的数字比较。
前面的数字8比4大,要移动4的位置,先将4存到临时位置,将8写到4的位置也就是数组中第五个位置,下来4继续和前面的数字5比较,5>4,于是将5又写到数组中第四个位置。
下来4接着和前面的数字比较,前面的数字1、0都小于4,所以将4写到以前5的位置,也就是数组中第三位。
下来接在用数组中第六个数3依次和前面的数字比较。
3前面的是8,8>3,需要移动3的位置,将3临时存起来,将8写到原来3的位置(数组中第六位)。
下来3和前面的5比较,5>3,所以将5写到原来8的位置(数组中第五位)。
下来3和前面的4比较,4>3,所以将4写到原来5的位置(数组中第四位)。
下来3继续和前面的1、0比较。前面的两个数都小于3,所以将临时位置中的3写到数组中第三位。
下来继续用数组中后面的数字依次和前面的数字比较,直到数组中最后一个数和前面的数都比较完成为止,说明数组中所有数的顺序已经拍好了。
insertSort test
原始数组:0 8 1 5 4 3 7 9 2 6
第 1趟 : 0 8 8 5 4 3 7 9 2 6
调整后为: 0 1 8 5 4 3 7 9 2 6
第 2趟 : 0 1 8 8 4 3 7 9 2 6
调整后为: 0 1 5 8 4 3 7 9 2 6
第 3趟 : 0 1 5 8 8 3 7 9 2 6
第 4趟 : 0 1 5 5 8 3 7 9 2 6
调整后为: 0 1 4 5 8 3 7 9 2 6
第 5趟 : 0 1 4 5 8 8 7 9 2 6
第 6趟 : 0 1 4 5 5 8 7 9 2 6
第 7趟 : 0 1 4 4 5 8 7 9 2 6
调整后为: 0 1 3 4 5 8 7 9 2 6
第 8趟 : 0 1 3 4 5 8 8 9 2 6
调整后为: 0 1 3 4 5 7 8 9 2 6
第 9趟 : 0 1 3 4 5 7 8 9 9 6
第 10趟 : 0 1 3 4 5 7 8 8 9 6
第 11趟 : 0 1 3 4 5 7 7 8 9 6
第 12趟 : 0 1 3 4 5 5 7 8 9 6
第 13趟 : 0 1 3 4 4 5 7 8 9 6
第 14趟 : 0 1 3 3 4 5 7 8 9 6
调整后为: 0 1 2 3 4 5 7 8 9 6
第 15趟 : 0 1 2 3 4 5 7 8 9 9
第 16趟 : 0 1 2 3 4 5 7 8 8 9
第 17趟 : 0 1 2 3 4 5 7 7 8 9
调整后为: 0 1 2 3 4 5 6 7 8 9
总共经过17趟数据交换之后,数组中的数据从小到大排列完成。
下面测试一下如果数组中的数最最坏情况下排序,看看用直接插入排序法需要多少趟。
insertSort test
原始数组:9 8 7 6 5 4 3 2 1 0
第 1趟 : 9 9 7 6 5 4 3 2 1 0
调整后为: 8 9 7 6 5 4 3 2 1 0
第 2趟 : 8 9 9 6 5 4 3 2 1 0
第 3趟 : 8 8 9 6 5 4 3 2 1 0
调整后为: 7 8 9 6 5 4 3 2 1 0
第 4趟 : 7 8 9 9 5 4 3 2 1 0
第 5趟 : 7 8 8 9 5 4 3 2 1 0
第 6趟 : 7 7 8 9 5 4 3 2 1 0
调整后为: 6 7 8 9 5 4 3 2 1 0
第 7趟 : 6 7 8 9 9 4 3 2 1 0
第 8趟 : 6 7 8 8 9 4 3 2 1 0
第 9趟 : 6 7 7 8 9 4 3 2 1 0
第 10趟 : 6 6 7 8 9 4 3 2 1 0
调整后为: 5 6 7 8 9 4 3 2 1 0
第 11趟 : 5 6 7 8 9 9 3 2 1 0
第 12趟 : 5 6 7 8 8 9 3 2 1 0
第 13趟 : 5 6 7 7 8 9 3 2 1 0
第 14趟 : 5 6 6 7 8 9 3 2 1 0
第 15趟 : 5 5 6 7 8 9 3 2 1 0
调整后为: 4 5 6 7 8 9 3 2 1 0
第 16趟 : 4 5 6 7 8 9 9 2 1 0
第 17趟 : 4 5 6 7 8 8 9 2 1 0
第 18趟 : 4 5 6 7 7 8 9 2 1 0
第 19趟 : 4 5 6 6 7 8 9 2 1 0
第 20趟 : 4 5 5 6 7 8 9 2 1 0
第 21趟 : 4 4 5 6 7 8 9 2 1 0
调整后为: 3 4 5 6 7 8 9 2 1 0
第 22趟 : 3 4 5 6 7 8 9 9 1 0
第 23趟 : 3 4 5 6 7 8 8 9 1 0
第 24趟 : 3 4 5 6 7 7 8 9 1 0
第 25趟 : 3 4 5 6 6 7 8 9 1 0
第 26趟 : 3 4 5 5 6 7 8 9 1 0
第 27趟 : 3 4 4 5 6 7 8 9 1 0
第 28趟 : 3 3 4 5 6 7 8 9 1 0
调整后为: 2 3 4 5 6 7 8 9 1 0
第 29趟 : 2 3 4 5 6 7 8 9 9 0
第 30趟 : 2 3 4 5 6 7 8 8 9 0
第 31趟 : 2 3 4 5 6 7 7 8 9 0
第 32趟 : 2 3 4 5 6 6 7 8 9 0
第 33趟 : 2 3 4 5 5 6 7 8 9 0
第 34趟 : 2 3 4 4 5 6 7 8 9 0
第 35趟 : 2 3 3 4 5 6 7 8 9 0
第 36趟 : 2 2 3 4 5 6 7 8 9 0
调整后为: 1 2 3 4 5 6 7 8 9 0
第 37趟 : 1 2 3 4 5 6 7 8 9 9
第 38趟 : 1 2 3 4 5 6 7 8 8 9
第 39趟 : 1 2 3 4 5 6 7 7 8 9
第 40趟 : 1 2 3 4 5 6 6 7 8 9
第 41趟 : 1 2 3 4 5 5 6 7 8 9
第 42趟 : 1 2 3 4 4 5 6 7 8 9
第 43趟 : 1 2 3 3 4 5 6 7 8 9
第 44趟 : 1 2 2 3 4 5 6 7 8 9
第 45趟 : 1 1 2 3 4 5 6 7 8 9
调整后为: 0 1 2 3 4 5 6 7 8 9
共执行了45次!
再测试下数组中数为最好情况下需要多少趟
最好的情况下,不需要交换数据。
下面测试一下随机生成10000个数据,排序需要的次数和时间。
用一张动图来演示一下排序过程