插入排序

来源:互联网 发布:软件项目转包合同范本 编辑:程序博客网 时间:2024/05/16 06:19

一、什么是插入排序?

每次讲一个待排序的元素,按其关键字的大小插入到已排好序的表中,直到全部元素插入完成为止。这里默认为增序。

二、常见的插入排序

(1)、直接插入排序

设数组为a[0…n],步骤如下:

1.  将原序列分成有序区和无序区,其中a[0…i-1]为有序区,a[i…n] 为无序区(i从1开始);

2.  从无序区中取出第一个元素,即a[i],在有序区序列中从后向前扫描;

3.  如果有序元素大于a[i],将该有序元素后移到下一位置;

4.  重复步骤3,直到找到小于或者等于a[i]的有序元素,将a[i]插入到该有序元素的下一位置中;

5.  重复步骤2~4,直到无序区元素为0。

可通过下面的动态图来理解:

代码如下:

void InsertSort(int seq[],int n){int  i,j; int temp;for(i=1;i<n;i++){temp=seq[i];  //要插入的数据j=i-1;while(j>=0&&seq[j]>temp){seq[j+1]=seq[j]; //后移j--;}seq[j+1]=temp;}}

(2)、二分插入排序

设数组为a[0…n],步骤如下:

1.  将原序列分成有序区和无序区,a[0…i-1]为有序区,a[i…n] 为无序区(i从1开始);

2.  从无序区中取出第一个元素,即a[i],使用二分查找算法在有序区中查找要插入的位置索引j;

3.  将a[j]到a[i-1]的元素后移,并将a[i]赋值给a[j];

4.  重复步骤2~3,直到无序区元素为0。

代码如下:

void InsertSort(int seq[],int  n){int  i,j,low,high,mid;int temp;for(i=1;i<n;i++){temp=seq[i];high=i-1;//该while循环用于查找temp应该插入的位置//在本次while循环的最后一次循环时,low==high==mid,接着要么if,要么else,while(low<=high){mid=(low+high)/2;if(temp<seq[mid]){high=mid-1;}else{low=mid+1;}}for(j=i-1;j>=high+1;j--){seq[j+1]=seq[j];}seq[high+1]=temp;}}


上述程序中,for循环嵌套这while循环,在while循环的最后一次循环时,low=mid=high,接着要么if,要么else,如下图所示,

若if,则意味着该未排序的元素应该插入到mid位置的前一个位置,即high=mid-1处,而此时的high<mid,故结束while循环;

若else,则意味着该未排序的元素应该插入到mid位置的后一个位置,即low=mid+1处,而此时的high<mid,故结束while循环。

因此,在结束while循环后,都应该将此时的high(不包括high)以后的元素往后移一位。

(3)、希尔排序(ShellSort)

基本思想:

先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。

先在各组内进行直接插人排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),

即所有记录放在同一组中进行直接插入排序为止。该方法实质上是一种分组插入方法。

可参考这里的动画来理解。http://student.zjzk.cn/course_ware/data_structure/web/flashhtml/shell.htm

代码如下:

void ShellSort(int R[],int n){int gap,i,j,temp;gap=n/2;for(i=gap;i<n;i++){j=i-gap;temp=R[i];while(j>=0&&temp<R[j]){R[j+gap]=R[j];j=j-gap;}R[j+gap]=temp;}gap=gap/2;}

参考:http://student.zjzk.cn/course_ware/data_structure/web/paixu/paixu8.2.2.1.htm

           http://www.cnblogs.com/heyuquan/p/insert-sort.html



0 0