插入排序,希尔排序

Posted on 2018-12-24 11:00  金色的省略号  阅读(221)  评论(0编辑  收藏  举报

插入排序

    一、定义:将数组分成左右2个部分,左边的是有序的,右边的是无序的,按正序或反序,逐个把右边无序的插入到左边有序的,最终完成排序。

  实现:

    1.移动法

    先把数组第0个元素看作是有序的,第1个元素之后是无序的,把第1个元素取出来保存,并与第0个元素进行比较,如果第0个元素大(或小),移动第0个元素到第1个元素位置(把第0个元素的值赋值给第1个元素),然后把保存的原第1个元素的值,赋值给第0个元素,实现插入,第0、1元素有序;然后把第2个元素取出来保存,并与其之前的有序元素从右向左,逐个比较,移动、插入,移动的条件是大(或小),插入的条件是不再大(或小)或者第0个元素也已经移动;第3、4...以此类推。

  c语言代码:

 

 1 /*插入排序*/
 2 #include <stdio.h>
 3 void InsertSort(int *arr, int n)
 4 {
 5     int i;
 6     for(i=1; i<n; ++i){/*第0个元素有序,从第1个元素向右无序*/
 7         int j=i-1,key=arr[i];/*保存第i个元素,左边的元素i-1*/
 8         while(j>=0 && key<arr[j]){/*保存的元素key与之前的元素从右向左逐个比较*/
 9             arr[j+1]=arr[j];/*移动(向后赋值)*/
10             j--;
11         }
12         arr[j+1]=key;/*j--退出,恢复正确值j+1*/
13     }
14 }
15 int main()
16 {
17     int i, arr[5]={9,8,1,4,3};
18     InsertSort(arr,5);
19     for(i=0; i<5; ++i)
20         printf("%d ",arr[i]);
21     printf("\n");
22     return 0;
23 }

 

        2.交换法

    先把数组第0个元素看作是有序的,第1个元素之后是无序的,把第1个元素,与第0个元素进行比较,如果第0个元素大(或小),交换,实现插入,第0、1元素有序;然后,第2个元素,与其之前的有序元素从右向左,逐个比较,交换,实现原来第2个元素的插入、有序;第3、4...以此类推。

  c语言代码:

 

 1 /*插入排序*/
 2 #include <stdio.h>
 3 
 4 void Swap(int *a, int *b);
 5 void InsertSort(int *arr, int n);
 6 
 7 int main()
 8 {
 9     int i, arr[5]={9,8,1,4,3};
10     InsertSort(arr,5);
11     for(i=0; i<5; ++i)
12         printf("%d ",arr[i]);
13     printf("\n");
14     return 0;
15 }
16 
17 void Swap(int *a, int *b)
18 {
19     int t = *a;
20     *a = *b;
21     *b = t;
22 }
23 
24 void InsertSort(int *arr, int n)
25 {
26     int i;
27     for(i=1; i<n; ++i){/*第0个元素有序,从第1个元素向右无序*/
28         int j=i;/*从第i个元素开始*/
29         while(j>0 && arr[j-1]>arr[j]){/*与之前的元素从右向左逐个比较*/
30             Swap(&arr[j-1],&arr[j]);/*交换,把原第i个元素的值向左推进*/
31             j--;
32         }
33     }
34 }

  

  二、插入排序的最好情况时间复杂度是O(N),最坏情况时间复杂度是O(N2),插入算法是稳定的;逆序对数即交换次数,如果序列基本有序,插入排序简单且高效,提高算法效率,每次不止消掉一个逆序对,即每次交换间隔较远的两个元素

 

void InsertionSort( ElementType A[], int N )
{ /* 插入排序 */
     int P, i;
     ElementType Tmp;
      
     for ( P=1; P<N; P++ ) {
         Tmp = A[P]; /* 取出未排序序列中的第一个元素*/
         for ( i=P; i>0 && A[i-1]>Tmp; i-- )
             A[i] = A[i-1]; /*依次与已排序序列中元素比较并右移*/
         A[i] = Tmp; /* 放进合适的位置 */
     }
}

   

  三、希尔排序,是不稳定的,

增量序列,Dk间隔有序的序列,在进行Dk-1间隔排序后,Dk间隔依然是有序的

 

void ShellSort( ElementType A[], int N )
{ /* 希尔排序 - 用Sedgewick增量序列 */
     int Si, D, P, i;
     ElementType Tmp;
     /* 这里只列出一小部分增量 */
     int Sedgewick[] = {929, 505, 209, 109, 41, 19, 5, 1, 0};
      
     for ( Si=0; Sedgewick[Si]>=N; Si++ ) 
         ; /* 初始的增量Sedgewick[Si]不能超过待排序列长度 */
 
     for ( D=Sedgewick[Si]; D>0; D=Sedgewick[++Si] )
         for ( P=D; P<N; P++ ) { /* 插入排序*/
             Tmp = A[P];
             for ( i=P; i>=D && A[i-D]>Tmp; i-=D )
                 A[i] = A[i-D];
             A[i] = Tmp;
         }
}