1.直接插入排序
直接插入排序的過程可以理解為一個固定長度的數組被分為兩個集合,即已排序集合和未排序。
開始時已排序集合為空,而未排序集合即為整個數組。當排序開始后插入一個對象,已排序集合元素數目加1,相應地未排序集合元素數目減1,重復插入過程直至將未排序集合清空為止,這時排序集合就是最終結果。如下圖:
C++實現如下,為了使得程序可以對各種基本數據類型都能排序,使用了模板類,注意模板類的類聲明和成員函數實現必須在同一個cpp文件里面,不能分開!!
1 #ifndef INSERTSORT_H 2 #define INSERTSORT_H
3 #include <vector>
4 #include <iostream>
5 using std::cout; 6 using std::endl; 7 using std::vector; 8
9 template <typename T>
10 class InsertSort 11 { 12 private: 13 unsigned len; 14 vector<T> list; 15 public: 16 InsertSort(vector<T> _list, unsigned _len) 17 { 18 for (unsigned i = 0; i < _len; ++i) list.push_back(_list[i]); 19 this->len = _len; 20 } 21 void insertSort() 22 { 23 T insertNum; 24 for (unsigned i = 0; i < len; ++i) // Insert number for len times
25 { 26 insertNum = list[i]; // The number is to be inserted
27 unsigned j = i; 28 while (j && insertNum < list[j-1]) // Find the position to insert the target number in
29 { 30 list[j] = list[j - 1]; 31 --j; 32 } 33 list[j] = insertNum; 34 } 35 } 36 void out() 37 { 38 for (unsigned i = 0; i < len; ++i) 39 { 40 cout << list[i] << " "; 41 if ((i+1)%18 == 0) cout << endl; 42 } 43 cout << endl; 44 } 45 }; 46 #endif
2.二分插入排序
因為直接插入排序在搜索插入位置的時候,效率很低,對於大數組,尤其不適用,於是采用二分插入排序,又叫折半插入排序,二分插入排序是采用折半查找法尋找要插入的位置。
下面演示了折半查找法在目標數組中確定數字35的位置:
- 首先確定目標數組的中間位置數字為45
- 由於45 > 35,所以降原數組折半並取左半部分子數組作為搜索目標,左半部分的中間元素為23
- 由於23 < 35,所以再折半,選擇子數組的有半部分作為搜索目標
- 而35 < 36,於是確定35的位置在23和36之間。
下面給出C++實現:
1 #ifndef BINARYINSERTSORT_H 2 #define BINARYINSERTSORT_H
3 #include <vector>
4 using std::vector; 5 template <typename T>
6 class BinaryInsertSort 7 { 8 private: 9 int len; 10 vector<T> list; 11 public: 12 BinaryInsertSort(vector<T> _list, int _len) 13 { 14 for (int i = 0; i < _len; ++i) list.push_back(_list[i]); 15 this->len = _len; 16 } 17 void binaryInsertSort() 18 { 19 int middle; 20 for (int i = 0; i < len; ++i) 21 { 22 T insertNum = list[i]; 23 int left = 0; 24 int right = i - 1; 25 while (left <= right)//Find the insertation position with binary search
26 { 27 middle = (left + right) / 2; 28 if (insertNum > list[middle]) 29 left = middle + 1; 30 else
31 right = middle - 1; 32 } 33 for (int j = i; j > left; --j) list[j] = list[j-1]; 34 list[left] = insertNum; 35 } 36 } 37 void out() 38 { 39 for (unsigned i = 0; i < len; ++i) 40 { 41 cout << list[i] << " "; 42 if ((i+1)%18 == 0) cout << endl; 43 } 44 cout << endl; 45 } 46 }; 47 #endif
3.測試運行
1 #include "InsertSort.h"
2 #include "BinaryInsertSort.h"
3 #include <vector>
4 using namespace std; 5
6 const unsigned numEle = 8; 7 int data[numEle] = {1,5,7,3,8,2,6,4}; 8
9
10 int main() 11 { 12 vector<int> testData; 13 for (unsigned i = 0; i < numEle; ++i) testData.push_back(data[i]); 14 //InsertSort<int> test(testData, numEle); 15 //test.insertSort();
16 BinaryInsertSort<int> test(testData, numEle); 17 test.binaryInsertSort(); 18 test.out(); 19 return 0; 20
21 }
4. 參考文獻
左飛:C++數據結構原理與經典問題求解