九大排序之——插入排序

来源:互联网 发布:网络舆论论文 编辑:程序博客网 时间:2024/06/04 20:11

直接插入排序:


思想:


将要排序的序列看成两个序列,一个是有序序列,另一个是无序序列,每次取无序序列中的元素往有序序列中的合适位置插入,直到无序序列为空,排序完成。


图解示例(红色为有序序列黑色为无序序列)




执行步骤:


(1)一个数可以认为是有序的,所以第一次区间划分如上图;

(2)在无序序列中取一个数,从有序序列的最后一个数开始向前扫描,若该元素大于前一个元素则插入该位置;

(3)重复执行(2);

(4)待无序序列为空时排序完成。


代码实现:


#include<iostream>#include<assert.h>using namespace std;template<class T>void Print(const T* a, size_t n){for (size_t i = 0; i < n; ++i){cout << a[i] << " ";}cout << endl;}template<class T>struct Less//升序{bool operator()(const T& l, const T& r){return l < r;}};template <class T>struct Great//降序{bool operator()(const T& l, const T& r){return l > r;}};template<class T,class Compare>void InsertSort(T* a, size_t n)//插入排序{assert(a);for (size_t i = 1; i < n; ++i){int end = i - 1;//end用来保存有序区间的最后一个数据的位置T temp = a[i];//temp用来保存无序区间的第一个数据,也是即将要插入有序区间的数据while (end >= 0){if (Compare()(temp, a[end]))//利用仿函数实现比较{a[end + 1] = a[end];//为temp[i]留出合适的位置end--;}elsebreak;}a[end+1] = temp;//将temp插入到合适的位置}}void TestInsertSort(){int a[] = { 3, 5, 7, 2, 4, 1, 9, 8, 6 };InsertSort<int, Less<int>>(a, sizeof(a) / sizeof(a[0]));//升序Print(a, sizeof(a) / sizeof(a[0]));InsertSort<int, Great<int>>(a, sizeof(a) / sizeof(a[0]));//降序Print(a, sizeof(a) / sizeof(a[0]));}template<class T,class Compare>void ShellSort(T* a,size_t n){assert(a);int gap = n;while (gap > 1){gap = gap / 3 + 1;//+1是为了最后一次对全体数据进行插入排序for (size_t i = gap; i < n; i++){int end = i - gap;T tmp = a[i];while (end >= 0){if (Compare()(tmp, a[end])){a[end + gap] = a[end];end = end - gap;}elsebreak;}a[end + gap] = tmp;}}}void TestShellSort(){int a[] = { 2, 5, 4, 9, 3, 6, 8, 7, 1, 0 };ShellSort<int, Less<int>>(a, sizeof(a) / sizeof(a[0]));Print(a, sizeof(a) / sizeof(a[0]));ShellSort<int, Great<int>>(a, sizeof(a) / sizeof(a[0]));Print(a, sizeof(a) / sizeof(a[0]));}template<class T,class Compare>void SelectSort(T* a, size_t n){assert(a);for (size_t i = 1; i < n; ++i){int minIndex = i;//未排序区间的最小数据下标int start = i - 1;//未排序区间的第一个数据下标//选出第二部分最小数据for (size_t j = i + 1; j < n - 1; ++j)//用i+1来不断的缩小j的范围{if (Compare()(a[j + 1], a[minIndex]))swap(a[j + 1], a[minIndex]);elsebreak;}//第二部分最小数据和第三部第一个数据进行比较if (Compare()(a[minIndex], a[start]))swap(a[minIndex], a[start]);}}void TestSelectSort(){int a[] = { 2, 5, 4, 9, 3, 6, 8, 7, 1, 0 };SelectSort<int, Less<int>>(a, sizeof(a) / sizeof(a[0]));Print(a, sizeof(a) / sizeof(a[0]));SelectSort<int, Great<int>>(a, sizeof(a) / sizeof(a[0]));Print(a, sizeof(a) / sizeof(a[0]));}


运行结果:



复杂度与稳定性分析:


最坏时间复杂度:O(n^2)序列处于逆序或基本逆序的情况下

最好时间复杂度:O(n)序列有序或基本有序的情况下

空间复杂度:O(1)

性:稳定