一、相關概念
1、增排序和減排序:如果排序的結果是按關鍵字從小到大的次序排列的,就是增排序,否則就是減排序。
2、穩定排序和不穩定排序:假設Ki=Kj(1≤i≤n,1≤j≤n,i≠j),且在排序前的序列中Ri領先於Rj(即i<j)。若在排序後的排序中Ri仍領先於Rj,即那些具有相同關鍵字的記錄,經過排序後它們的相對次序仍然保持不變,則稱這種排序方法是穩定的;反之,若Rj領先於Ri,則稱所用的方法是不穩定的。
3、排序:將原有表中任意順序的記錄變成一個按關鍵字有序排列的過程稱爲排序。
4、內部排序與外部排序:在排序中,若數據表中的所有記錄的排列過程都是在內存中進行的,稱爲內部排序。由於待排序的記錄數量太多,在排序過程中不能同時把全部記錄放在內存,需要不斷地通過在內存和外存之間交換數據元素來完成整個排序的過程,稱爲外部排序。在外部排序情況下,只有部分記錄進入內存,在內存中進行內部排序,待排序完成後再交換到外部存儲器中加以保存。然後再將其它待排序的記錄調入內存繼續排序。這一過程需要反覆進行,直到全部記錄排出次序爲止。顯然,內部排序是外部排序的基礎。
二、插入排序的算法思想
插入排序的基本思想是:每次將一個待排序的記錄,按其關鍵字大小插入到前面已經排好序的子表中的適當位置,直到全部記錄插入完成爲止。也就是說,將待序列表分成左右兩部分,左邊爲有序表(有序序列),右邊爲無序表(無序序列)。整個排序過程就是將右邊無序表中的記錄逐個插入到左邊的有序表中,構成新的有序序列。根據不同的插入方法,插入排序算法主要包括:直接插入排序、折半插入排序、表插入排序和希爾排序等。我們學習介紹直接插入排序、折半插入排序和希爾排序。
1、直接插入排序
基本原理是順次地從無序表中取出記錄Ri(1≤i≤n),與有序表中記錄的關鍵字逐個進行比較,找出其應該插入的位置,再將此位置及其之後的所有記錄依次向後順移一個位置,將記錄Ri插入其中。
假設待排序的n個記錄爲{R1,R2 ,……,Rn},初始有序表爲[R1],初始無序表爲[R2 …Rn]。當插入第i個記錄Ri(2≤i≤n)時,有序表爲[R1…Ri-1],無序表爲[Ri …Rn]。將關鍵字K i依次與Ki-1,Ki-2 ,…,K1進行比較,找出其應該插入的位置,將該位置及其以後的記錄向後順移,插入記錄Ri,完成序列中第i個記錄的插入排序。當完成序列中第n個記錄Rn的插入後,整個序列排序完畢。
向有序表中插入記錄,主要完成如下操作:
(1) 搜索插入位置。
(2) 移動插入點及其以後的記錄空出插入位置。
(3) 插入記錄。
假設將n個待排序的記錄順序存放在長度爲n+1的數組R[1]~R[n] 中。R[0]作爲輔助空間,用來暫時存儲需要插入的記錄,起監視哨的作用。該算法是穩定的。
實際算法中,0單元的變化並不如上圖所示。在這裏只是說明0單元的作用除了輔助存儲空間外,還有監視哨作用,顯示當前處理的記錄。
2、折半插入排序
直接插入排序的基本操作是在有序表中進行查找和插入,而在有序表中查找插入位置,可以通過折半查找的方法實現,由此進行的插入排序稱之爲折半插入排序。折半查找的過程是以處於有序表中間位置記錄的關鍵字和Ki比較,經過一次比較,便可排除一半記錄,把可插入的區間縮小一半,故稱爲折半。折半插入排序僅減少了關鍵字間的比較次數,但記錄的移動次數不變。因此折半插入排序的時間複雜度仍爲O(n2)。折半插入排序的空間複雜度與直接插入排序相同。折半插入排序也是一個穩定的排序方法。
3、希爾排序
希爾排序(shell’s sort)又稱縮小增量排序(DiminishingIncrement Sort)。它是希爾(D.L.Shell)於1959年提出的插入排序的改進算法。如前所述,直接插入排序算法的時間性能取決於數據的初始特性,一般情況下,它的時間複雜度爲O(n2)。但是當待排序列爲正序或基本有序時,時間複雜度則爲O(n)。因此,若能在一次排序前將排序序列調整爲基本有序,則排序的效率就會大大提高。正是基於這樣的考慮,希爾提出了改進的插入排序方法。
希爾排序的基本思想是:先將整個待排記錄序列分割成若干小組(子序列),分別在組內進行直接插入排序,待整個序列中的記錄“基本有序”時,再對全體記錄進行一次直接插入排序。分割方法:選定一個記錄的間隔值d,將所有間隔d的記錄作爲一組。在組內進行直接插入排序。然後縮小間隔,重新分組,再進行組內重新排序,直到間隔爲1爲止。
三、插入排序的C語言描述
1、直接插入排序
2、折半插入排序
3、希爾排序
四、插入排序的C語言實現
#include"stdio.h"
#include"stdlib.h"
#include"math.h"
#define OK 1
#define MAXSIZE 20
typedef intKeyType;
typedef intStatus;
typedef struct
{
KeyType key;
//InfoTypeotherinfo;
}RedType;
typedef struct
{
RedTyper[MAXSIZE+1];
int length;
}Sqlist;
voidBInsertSort(Sqlist &L)
{
int low,high;
for(inti=2;i<=L.length;++i)
{
L.r[0]=L.r[i];
low=1;
high=i-1;
while(low<=high)
{
int m;
m=(low+high)/2;
if(L.r[0].key<L.r[m].key) high=m-1;
else low=m+1;
}//while
for(int j=i-1;j>=high+1;--j)
L.r[j+1]=L.r[j];
L.r[high+1]=L.r[0];
}//for
}//BInsertSort
voidInsertSort(Sqlist &L)
{
int i,j;
for(i=2;i<=L.length;++i){
if(L.r[i].key<L.r[i-1].key)
{
L.r[0]=L.r[i];
for(j=i-1;L.r[0].key<L.r[j].key;j--)
L.r[j+1]=L.r[j];
L.r[j+1]=L.r[0];
}//if
printf("i=%d: L.[0].key:%d\n",i,L.r[0].key);
}
}
voidShellInsert(Sqlist &L,int dk)
{
int i,j;
for(i=dk+1;i<=L.length;++i)
if(L.r[i].key<L.r[i-dk].key)
{
L.r[0]=L.r[i];
for(j=i-dk;j>0&&(L.r[0].key<L.r[j].key);j-=dk)
L.r[j+dk]=L.r[j];
L.r[j+dk]=L.r[0];
}//if,for
}//ShellInsertS
voidShellSort(Sqlist &L,int dlta[],int t)
{
for(intk=1;k<=t;++k)
ShellInsert(L,dlta[k]);
}
void InputL(Sqlist&L)
{
printf("inputthe length:\n");
scanf("%d",&L.length);
printf("inputthe data needed to sort:\n");
for(inti=1;i<=L.length;i++)
scanf("%d",&L.r[i].key);
}//InputL
voidOutputL(Sqlist &L)
{
printf("thedata after sorting is:\n");
for(int i=1;i<=L.length;i++)
printf("%d ",L.r[i].key);
}
void dimish(Sqlist&L,int dlta[],int &t)
{
t=(int)floor(log10(L.length+1)/log10(2));
for(intk=1;k<=t;k++)
dlta[k]=(int)(pow(2,t-k+1)-1);
}
int main()
{
Sqlist L;
InputL(L);
intdlta[MAXSIZE],t;
//BInsertSort(L);
//InsertSort(L);
dimish(L,dlta,t);//calculatethe dlat for shellSort
ShellSort(L,dlta,t);
OutputL(L);
return OK;
}