數據結構排序算法總結

  文章篇幅有點大,請點擊查看更多,下面是跳轉連接:

 

    1、插入排序  1)直接插入排序  2)折半插入排序  3)希爾排序html

    2、交換排序  1)冒泡排序    2)快速排序算法

    3、選擇排序  1)簡單選擇排序  2)堆排序函數

    4、歸併排序ui

    5、基數排序spa

 

1、插入排序指針


1)直接插入排序    算法演示        返回目錄code

  時間複雜度:平均狀況—O(n2)    最壞狀況—O(n2)    輔助空間:O(1)    穩定性:穩定orm

?
1
2
3
4
5
6
7
8
9
10
11
12
void InsertSort(SqList &L) {
   // 對順序表L做直接插入排序。
   int i,j;
   for (i=2; i<=L.length; ++i)
     if (LT(L.r[i].key, L.r[i-1].key)) {
       // "<"時,需將L.r[i]插入有序子表
       L.r[0] = L.r[i];                 // 複製爲哨兵
       for (j=i-1;  LT(L.r[0].key, L.r[j].key);  --j)
         L.r[j+1] = L.r[j];             // 記錄後移
       L.r[j+1] = L.r[0];               // 插入到正確位置
     }
} // InsertSort   


2)折半插入排序        返回目錄htm

  時間複雜度:平均狀況—O(n2)     穩定性:穩定blog

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void BInsertSort(SqList &L) {
   // 對順序表L做折半插入排序。
   int i,j,high,low,m;
   for (i=2; i<=L.length; ++i) {
     L.r[0] = L.r[i];       // 將L.r[i]暫存到L.r[0]
     low = 1;   high = i-1;
     while (low<=high) {    // 在r[low..high]中折半查找有序插入的位置
       m = (low+high)/2;                            // 折半
       if (LT(L.r[0].key, L.r[m].key)) high = m-1;  // 插入點在低半區
       else  low = m+1;                             // 插入點在高半區
     }
     for (j=i-1; j>=high+1; --j) L.r[j+1] = L.r[j];  // 記錄後移
     L.r[high+1] = L.r[0];                           // 插入
   }
} // BInsertSort

 

 

3)希爾排序    算法演示        返回目錄

  時間複雜度:理想狀況—O(nlog2n)     最壞狀況—O(n2)     穩定性:不穩定


 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void ShellInsert(SqList &L, int dk) {
   // 對順序表L做一趟希爾插入排序。本算法對算法10.1做了如下修改:
   //     1. 先後記錄位置的增量是dk,而不是1;
   //     2. r[0]只是暫存單元,不是哨兵。當j<=0時,插入位置已找到。
   int i,j;
   for (i=dk+1; i<=L.length; ++i)
     if (LT(L.r[i].key, L.r[i-dk].key)) { // 需將L.r[i]插入有序增量子表
       L.r[0] = L.r[i];                   // 暫存在L.r[0]
       for (j=i-dk; j>0 && LT(L.r[0].key, L.r[j].key); j-=dk)
         L.r[j+dk] = L.r[j];              // 記錄後移,查找插入位置
       L.r[j+dk] = L.r[0];                // 插入
     }
} // ShellInsert  
  
void ShellSort(SqList &L, int dlta[], int t) {
    // 按增量序列dlta[0..t-1]對順序表L做希爾排序。
    for ( int k=0;k<t;k++)
       ShellInsert(L, dlta[k]);  // 一趟增量爲dlta[k]的插入排序
} // ShellSort

 

 

2、交換排序


1)冒泡排序    算法演示        返回目錄

  時間複雜度:平均狀況—O(n2)     最壞狀況—O(n2)     輔助空間:O(1)      穩定性:穩定

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void BubbleSort(SeqList R) {
   int i,j;
  Boolean exchange; //交換標誌
   for (i=1;i<n;i++){ exchange= "FALSE;" j= "n-1;j" >=i;j--) //對當前無序區R[i..n]自下向上掃描
            if (R[j+1].key< R[j].key){ //交換記錄
                R[0]=R[j+1]; //R[0]不是哨兵,僅作暫存單元
                R[j+1]=R[j];
                 R[j]=R[0];
                exchange=TRUE; //發生了交換,故將交換標誌置爲真
            }
            if (!exchange) //本趟排序未發生交換,提早終止算法
            return ;
  } //endfor(外循環)
} //BubbleSort</n;i++){>

 

 

2)快速排序    算法演示        返回目錄

  時間複雜度:平均狀況—O(nlog2n)     最壞狀況—O(n2)     輔助空間:O(log2n)      穩定性:不穩定

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
int Partition(SqList &L, int low, int high) {
  // 交換順序表L中子序列L.r[low..high]的記錄,使樞軸記錄到位,
    // 並返回其所在位置,此時,在它以前(後)的記錄均不大(小)於它
    KeyType pivotkey;
    RedType temp;
    pivotkey = L.r[low].key;     // 用子表的第一個記錄做樞軸記錄
    while (low < high) {           // 從表的兩端交替地向中間掃描
       while (low < high && L.r[high].key>=pivotkey) --high;
       temp=L.r[low];
       L.r[low]=L.r[high];
       L.r[high]=temp;           // 將比樞軸記錄小的記錄交換到低端
       while (low  < high && L.r[low].key < =pivotkey) ++low;
       temp=L.r[low];
       L.r[low]=L.r[high];
       L.r[high]=temp;           // 將比樞軸記錄大的記錄交換到高端
    }
    return low;                  // 返回樞軸所在位置
} // Partition        
  
int Partition(SqList &L, int low, int high) {
// 交換順序表L中子序列L.r[low..high]的記錄,使樞軸記錄到位,
    // 並返回其所在位置,此時,在它以前(後)的記錄均不大(小)於它
    KeyType pivotkey;
    L.r[0] = L.r[low];            // 用子表的第一個記錄做樞軸記錄
    pivotkey = L.r[low].key;      // 樞軸記錄關鍵字
    while (low < high) {            // 從表的兩端交替地向中間掃描
       while (low < high && L.r[high].key>=pivotkey) --high;
       L.r[low] = L.r[high];      // 將比樞軸記錄小的記錄移到低端
       while (low  < high && L.r[low].key  < =pivotkey) ++low;
       L.r[high] = L.r[low];      // 將比樞軸記錄大的記錄移到高端
    }
    L.r[low] = L.r[0];            // 樞軸記錄到位
    return low;                   // 返回樞軸位置
} // Partition        
  
void QSort(SqList &L, int low, int high) {
   // 對順序表L中的子序列L.r[low..high]進行快速排序
   int pivotloc;
   if (low  <  high) {                      // 長度大於1
     pivotloc = Partition(L, low, high);  // 將L.r[low..high]一分爲二
     QSort(L, low, pivotloc-1); // 對低子表遞歸排序,pivotloc是樞軸位置
     QSort(L, pivotloc+1, high);          // 對高子表遞歸排序
   }
} // QSort     
  
void QuickSort(SqList &L) {  // 算法10.8
    // 對順序表L進行快速排序
    QSort(L, 1, L.length);
} // QuickSort

 

3、選擇排序


1)簡單選擇排序    算法演示        返回目錄

時間複雜度:平均狀況—O(n2)     最壞狀況—O(n2)     輔助空間:O(1)      穩定性:不穩定


 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
void SelectSort(SqList &L) {
   // 對順序表L做簡單選擇排序。
   int i,j;
   for (i=1; i < L.length; ++i) { // 選擇第i小的記錄,並交換到位
     j = SelectMinKey(L, i);  // 在L.r[i..L.length]中選擇key最小的記錄
     if (i!=j) {                // L.r[i]←→L.r[j];   與第i個記錄交換
       RedType temp;
       temp=L.r[i];
       L.r[i]=L.r[j];
       L.r[j]=temp;
     }
   }
} // SelectSort

 

2)堆排序    算法演示        返回目錄

時間複雜度:平均狀況—O(nlog2n)     最壞狀況—O(nlog2n)     輔助空間:O(1)      穩定性:不穩定

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void HeapAdjust(HeapType &H, int s, int m) {
   // 已知H.r[s..m]中記錄的關鍵字除H.r[s].key以外均知足堆的定義,
   // 本函數調整H.r[s]的關鍵字,使H.r[s..m]成爲一個大頂堆
   // (對其中記錄的關鍵字而言)
   int j;
   RedType rc;
   rc = H.r[s];
   for (j=2*s; j < =m; j*=2) {   // 沿key較大的孩子結點向下篩選
     if (j < m && H.r[j].key < H.r[j+1].key) ++j; // j爲key較大的記錄的下標
     if (rc.key >= H.r[j].key) break ;         // rc應插入在位置s上
     H.r[s] = H.r[j];  s = j;
   }
   H.r[s] = rc;  // 插入
} // HeapAdjust    
  
void HeapSort(HeapType &H) {
    // 對順序表H進行堆排序。
    int i;
    RedType temp;
    for (i=H.length/2; i>0; --i)  // 把H.r[1..H.length]建成大頂堆
       HeapAdjust ( H, i, H.length );
       for (i=H.length; i>1; --i) {
          temp=H.r[i];
          H.r[i]=H.r[1];
          H.r[1]=temp;  // 將堆頂記錄和當前未經排序子序列Hr[1..i]中
                        // 最後一個記錄相互交換
          HeapAdjust(H, 1, i-1);  // 將H.r[1..i-1] 從新調整爲大頂堆
       }
} // HeapSort

 

4、歸併排序    算法演示        返回目錄

時間複雜度:平均狀況—O(nlog2n)      最壞狀況—O(nlog2n)      輔助空間:O(n)      穩定性:穩定


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void Merge (RedType SR[], RedType TR[], int i, int m, int n) {
    // 將有序的SR[i..m]和SR[m+1..n]歸併爲有序的TR[i..n]
    int j,k;
    for (j=m+1, k=i;  i < =m && j < =n;  ++k) {
       // 將SR中記錄由小到大地併入TR
       if LQ(SR[i].key,SR[j].key) TR[k] = SR[i++];
       else TR[k] = SR[j++];
    }
    if (i < =m)  // TR[k..n] = SR[i..m];  將剩餘的SR[i..m]複製到TR
       while (k < =n && i < =m) TR[k++]=SR[i++];
    if (j < =n)  // 將剩餘的SR[j..n]複製到TR
       while (k < =n &&j  < =n) TR[k++]=SR[j++];
} // Merge    
  
void MSort(RedType SR[], RedType TR1[], int s, int t) {
    // 將SR[s..t]歸併排序爲TR1[s..t]。
    int m;
    RedType TR2[20];
    if (s==t) TR1[t] = SR[s];
    else {
       m=(s+t)/2;            // 將SR[s..t]平分爲SR[s..m]和SR[m+1..t]
       MSort(SR,TR2,s,m);    // 遞歸地將SR[s..m]歸併爲有序的TR2[s..m]
       MSort(SR,TR2,m+1,t);  // 將SR[m+1..t]歸併爲有序的TR2[m+1..t]
       Merge(TR2,TR1,s,m,t); // 將TR2[s..m]和TR2[m+1..t]歸併到TR1[s..t]
    }
} // MSort    
  
void MergeSort(SqList &L) {
   // 對順序表L做歸併排序。
   MSort(L.r, L.r, 1, L.length);
} // MergeSort

 

 

5、基數排序    算法演示        返回目錄

 

時間複雜度:平均狀況—O(d(n+rd))      最壞狀況—O(d(n+rd))      輔助空間:O(rd)      穩定性:穩定

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void Distribute(SLList &L, int i, ArrType &f, ArrType &e) {
   // 靜態鏈表L的r域中記錄已按(keys[0],...,keys[i-1])有序,
   // 本算法按第i個關鍵字keys[i]創建RADIX個子表,
   // 使同一子表中記錄的keys[i]相同。f[0..RADIX-1]和e[0..RADIX-1]
   // 分別指向各子表中第一個和最後一個記錄。
   int j, p;
   for (j=0; j < RADIX; ++j) f[j] = 0;     // 各子表初始化爲空表
   for (p=L.r[0].next;  p;  p=L.r[p].next) {
     j = L.r[p].keys[i]- '0' // 將記錄中第i個關鍵字映射到[0..RADIX-1],
     if (!f[j]) f[j] = p;
     else L.r[e[j]].next = p;
     e[j] = p;                // 將p所指的結點插入第j個子表中
   }
} // Distribute    
  
void Collect(SLList &L, int i, ArrType f, ArrType e) {
   // 本算法按keys[i]自小至大地將f[0..RADIX-1]所指各子表依次連接成
   // 一個鏈表,e[0..RADIX-1]爲各子表的尾指針
   int j,t;
   for (j=0; !f[j]; j++);  // 找第一個非空子表,succ爲求後繼函數: ++
   L.r[0].next = f[j];  // L.r[0].next指向第一個非空子表中第一個結點
   t = e[j];
   while (j < RADIX) {
     for (j=j+1; j < RADIX && !f[j]; j++);       // 找下一個非空子表
     if (j < RADIX) // 連接兩個非空子表
       { L.r[t].next = f[j];  t = e[j]; }
   }
   L.r[t].next = 0;   // t指向最後一個非空子表中的最後一個結點
} // Collect    
  
void RadixSort(SLList &L) {
    // L是採用靜態鏈表表示的順序表。
    // 對L做基數排序,使得L成爲按關鍵字自小到大的有序靜態鏈表,
    // L.r[0]爲頭結點。
    int i;
    ArrType f, e;
    for (i=1; i < L.recnum; ++i) L.r[i-1].next = i;
    L.r[L.recnum].next = 0;     // 將L改造爲靜態鏈表
    for (i=0; i < L.keynum; ++i) {
       // 按最低位優先依次對各關鍵字進行分配和收集
       Distribute(L, i, f, e);    // 第i趟分配
       Collect(L, i, f, e);       // 第i趟收集
       print_SLList2(L, i);
    }
} // RadixSort
相關文章
相關標籤/搜索