1. 程式人生 > 實用技巧 >插入排序演算法(插入排序&折半插入排序&希爾排序)

插入排序演算法(插入排序&折半插入排序&希爾排序)

插入排序

概念

插入排序(Insertion-Sort)的演算法描述是一種簡單直觀的排序演算法。它的工作原理是通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃描,找到相應位置並插入。

這裡我們採用順序表的儲存方式來儲存資料

具體實現步驟

  1. 將待排序序列第一個元素看做一個有序序列,把第二個元素到最後一個元素當成是未排序序列;
  2. 取出下一個元素,在已經排序的元素序列中從後向前掃描;
  3. 如果該元素(已排序)大於新元素,將該元素移到下一位置;
  4. 重複步驟3,直到找到已排序的元素小於或者等於新元素的位置;
  5. 將新元素插入到該位置後;
  6. 重複步驟2~5。

程式碼實現

#include<iostream>
using
namespace std; #define MAXSIZE 50 typedef int keyType; typedef string other; typedef struct { keyType key; other data; //其他資料 }arrayType; typedef struct{ arrayType r[MAXSIZE+1]; // r[0]閒置或者作為哨兵而存在 int length; }SqList; void Sort(SqList &p) { int j; for(int i=2;i<=p.length;i++) {
if(p.r[i].key<p.r[i-1].key) { p.r[0].key=p.r[i].key; p.r[i].key = p.r[i-1].key; for(j = i-2;p.r[0].key<p.r[j].key;j--) { p.r[j+1].key = p.r[j].key; } p.r[j+1].key = p.r[0].key; } } } int main() {
int n,i; SqList arry; cout<<"請輸入需要排序的個數:"<<endl; cin>>n;arry.length=n; cout<<"請依次輸入這"<<n<<"個數:"<<endl; for(i=0;i<n;i++) { cin>>arry.r[i+1].key; } Sort(arry); cout<<"排序後:"<<endl; for(i=1;i<=n;i++) { cout<<arry.r[i].key<<" "; } return 0; }
插入排序

折半插入排序

概念

折半插入排序(Binary Insertion Sort)是對插入排序演算法的一種改進,所謂排序演算法過程,就是不斷的依次將元素插入前面已排好序的序列中。

排序思想

遍歷無序區間的所有元素,每次取無序區間的第一個元素Array[i],因為0~i-1是有序排列的,所以用中點m將其平分為兩部分,然後將待排序資料同中間位置為m的資料進行比較,若待排序資料較大,則low~m-1分割槽的資料都比待排序資料小,反之,若待排序資料較小,則m+1~high分割槽的資料都比 待排序資料大,此時將low或high重新定義為新的合適分割槽的邊界,對新的小分割槽重複上面操作。直到low和high 的前後順序改變,此時high+1所處位置為待排序資料的合適位置。

程式碼實現

#include<iostream>
using namespace std;
#define MAXSIZE  50
typedef int keyType;
typedef string other;
typedef struct
{
    keyType key;
    other  data;  //其他資料
}arrayType;

typedef struct{

   arrayType r[MAXSIZE+1];    //  r[0]閒置或者作為哨兵而存在
   int length;
}SqList;


void Sort(SqList &p)
{
    for(int i=2;i<=p.length;i++)
    {
        p.r[0].key=p.r[i].key;
        int low =1,high = i-1,m;
        if(p.r[i-1].key>p.r[i].key)
        {
            while(low<=high)
            {
                m =(low+high)/2;
                if(p.r[m].key<p.r[0].key)
                    low = m+1;
                else
                    high = m-1;
            }
            for(int j=i-1;j>high;j--)
                p.r[j+1].key = p.r[j].key;
            p.r[high+1]=p.r[0];
        }
    }
}
int main()
{
    int n,i;
    SqList arry;
   cout<<"請輸入需要排序的個數:"<<endl;
   cin>>n;arry.length=n;
   cout<<"請依次輸入這"<<n<<"個數:"<<endl;
   for(i=0;i<n;i++)
   {
       cin>>arry.r[i+1].key;
   }


   Sort(arry);


   cout<<"排序後:"<<endl;
   for(i=1;i<=n;i++)
   {
       cout<<arry.r[i].key<<" ";
   }
  return 0;
}

希爾排序

概念

希爾排序又叫做縮小增量排序,其本質還是插入排序,只是在將待排序序列按照某種規則分成幾個子序列,分別對這幾個子序列進行直接插入排序,

排序思想

首先它把較大的資料集合分割成若干個小組(邏輯上分組),然後對每一個小組分別進行插入排序,此時,插入排序所作用的資料量比較小(每一個小組),插入的效率比較高

程式碼實現

 1 #include<iostream>
 2 using namespace std;
 3 #define MAXSIZE  50
 4 typedef int keyType;
 5 typedef string other;
 6 typedef struct
 7 {
 8     keyType key;
 9     other  data;  //其他資料
10 }arrayType;
11 
12 typedef struct{
13 
14    arrayType r[MAXSIZE+1];    //  r[0]閒置或者作為哨兵而存在
15    int length;
16 }SqList;
17 
18 void ShellInsert(SqList &p,int dk)
19 {
20     for(int i=dk+1;i<=p.length;i++)
21     {
22         if(p.r[i].key<p.r[i-dk].key)
23         {
24             p.r[0] = p.r[i];
25             p.r[i]=p.r[i-dk];
26             p.r[i-dk]=p.r[0];
27         }
28     }
29 }
30 
31 void ShellSort(SqList &p,int dt[],int t)
32 {
33     for(int k=0;k<t;k++)
34     {
35        ShellInsert(p,dt[k]);
36     }
37 }
38 int main()
39 {
40      int n,i;
41     SqList arry;
42    cout<<"請輸入需要排序的個數:"<<endl;
43    cin>>n;arry.length=n;
44    cout<<"請依次輸入這"<<n<<"個數:"<<endl;
45    for(i=0;i<n;i++)
46    {
47        cin>>arry.r[i+1].key;
48    }
49  //增量序列
50     int dt[3] = {5,3,1};
51     ShellSort(arry,dt,3);
52 
53 
54    cout<<"排序後:"<<endl;
55    for(i=1;i<=n;i++)
56    {
57        cout<<arry.r[i].key<<" ";
58    }
59 
60   return 0;
61 }

插入總結

  1. 希爾排序不可以用於鏈式結構
  2. 空間複雜度都是O(1)
  3. 時間複雜度:O(n2),O(n2),n(log2n)2
  4. 插入排序適用於:小規模資料資料或者基本有序
    時十分高效。