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++数据结构原理与经典问题求解