插入排序:直接插入排序与希尔排序

      插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中的适当位置,直到全部记录插入完成为止。
    本节介绍两种插入排序方法:直接插入排序和希尔排序。

直接插入排序基本思想
1、基本思想

    假设待排序的记录存放在数组R[1..n]中。初始时,R[1]自成1个有序区,无序区为R[2..n]。从i=2起直至i=n为止,依次将R[i]插入当前的有序区R[1..i-1]中,生成含n个记录的有序区。

具体做法:
    将待插入记录R[i]的关键字从右向左依次与有序区中记录R[j](j=i-1,i-2,…,1)的关键字进行比较:
    ① 若R[j]的关键字大于R[i]的关键字,则将R[j]后移一个位置;
      ②若R[j]的关键字小于或等于R[i]的关键字,则查找过程结束,j+1即为R[i]的插入位置。
    关键字比R[i]的关键字大的记录均已后移,所以j+1的位置已经腾空,只要将R[i]直接插入此位置即可完成一趟直接插入排序。

package com.sqtds.algorithm.sort;

/**
* User: sqtds
* Date: 13-1-15
* Time: 下午3:44
*/
public class Insertion {

public static int[] sort(int[] array){
int[] temp = new int[array.length];
temp[0]=array[0];
for(int i =1 ; i<array.length ; i++){
insertArray(temp ,array[i],i);
}
return temp;
}

public static void insertArray(int[] array ,int num,int current){
for(int i = 0 ; i <current;i++){
if(num<array[i]){
shiftArray(array , i , num,current);
break;
}else if( i ==current-1){
array[current] = num;
}
}
}

public static void shiftArray(int[] array , int index ,int num,int current){
for(int i = current ;i>index ;i--){
array[i] = array[i-1];
}
array[index] = num;
}

public static void lnsertSort(int[] array)
{ //对顺序表R中的记录R[1..n]按递增序进行插入排序
int i , j ,t;
for( i=1 ; i< array.length ; i++) //依次插入R[2],…,R[n]
if(array[i]<array[i-1]){//若R[i].key大于等于有序区中所有的keys,则R[i]
//应在原有位置上
t =array[i];j=i-1; //R[0]是哨兵,且是R[i]的副本
do{ //从右向左在有序区R[1..i-1]中查找R[i]的插入位置
array[j+1]=array[j]; //将关键字大于R[i].key的记录后移
j-- ;
}while(j>=0&&t<array[j]); //当R[i].key≥R[j].key时终止
array[j+1]=t; //R[i]插入到正确的位置上
}//endif
}//InsertSort

public static void main(String args[]){
int[] array = {4,5,7,2,3,9,8,0,1};
int[] temp = sort(array);
lnsertSort(array);
for(int i : array){
System.out.print(i + " ");
}
}
}

希尔排序基本思想

  基本思想:
     先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
    该方法实质上是一种分组插入方法。

void ShellPass(SeqList R,int d)
{//希尔排序中的一趟排序,d为当前增量
for(i=d+1;i<=n;i++) //将R[d+1..n]分别插入各组当前的有序区
if(R[i].key<R[i-d].key){
R[0]=R[i];j=i-d; //R[0]只是暂存单元,不是哨兵
do {//查找R[i]的插入位置
R[j+d];=R[j]; //后移记录
j=j-d; //查找前一记录
}while(j>0&&R[0].key<R[j].key);
R[j+d]=R[0]; //插入R[i]到正确的位置上
} //endif
} //ShellPass

void ShellSort(SeqList R)
{
int increment=n; //增量初值,不妨设n>0
do {
increment=increment/3+1; //求下一增量
ShellPass(R,increment); //一趟增量为increment的Shell插入排序
}while(increment>1)
} //ShellSort


posted @ 2013-01-16 23:26  sqtds  阅读(176)  评论(0编辑  收藏  举报