#include <iostream> #include <iterator> #include <algorithm> #include <cstdlib> #include <vector> #include <cassert> std::vector<int> generateIntList(int size = 10) { std::vector<int> result_list; std::generate_n( std::back_insert_iterator<std::vector<int>>(result_list), size, []() { return std::rand() % 10; } ); return std::move(result_list); } void showIntList(const std::vector<int>& ll) { //std::cout << "list: "; std::copy(ll.begin(), ll.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << "\n"; } //插入排序 //每次遍歷保證p位置的元素,比p左邊的元素小 void insertSort(std::vector<int>& ll) { for (decltype(ll.size()) p = 1; p < ll.size(); ++p) { auto tmp = ll[p]; auto j = p; for (; j > 0 && tmp < ll[j - 1]; --j) { ll[j] = ll[j - 1]; } ll[j] = tmp; } } void insertSort(std::vector<int>& ll, int left, int right) { for (decltype(ll.size()) p = left + 1; p <= right; ++p) { auto tmp = ll[p]; auto j = p; for (; j > left && tmp < ll[j - 1]; --j) { ll[j] = ll[j - 1]; } ll[j] = tmp; } } //謝爾排序 //帶增量的插入排序。。。 void shellSort(std::vector<int>& ll) { for (auto gap = ll.size() / 2; gap > 0; gap /= 2) { for (auto p = gap; p < ll.size(); p++) { auto tmp = ll[p]; auto j = p; for (; j >= gap && tmp < ll[j - gap]; j -= gap) { ll[j] = ll[j - gap]; } ll[j] = tmp; } } } //堆排序 //先創建二叉大頂堆,交換堆頂元素和最後一個元素 //二叉堆的性質:位置在i的元素,左兒子在2i,右兒子在2i+1 //將位置i的元素下濾到指定的層數, 每次都是與左右兩個兒子中的較大值進行交換, 大於兩個兒子時中止下濾 void percDown(std::vector<int>& ll, int i, int n) { auto leftChild = [](const int i) -> int {return 2 * i + 1; }; int child; auto tmp = ll[i]; for (; leftChild(i) < n; i = child) { child = leftChild(i); if (child != n - 1 && ll[child] < ll[child + 1]) { ++child; } if (tmp < ll[child]) { ll[i] = ll[child]; } else { break; } } ll[i] = tmp; } void heapSort(std::vector<int>& ll) { //從下往上進行下濾操做,創建一個大頂堆 for (int i = ll.size() / 2; i >= 0; --i) { percDown(ll, i, ll.size()); } for (int j = ll.size() - 1; j > 0; --j) { std::swap(ll[0], ll[j]);//交換堆頂元素和最後一個元素 percDown(ll, 0, j);//對堆頂進行下濾操做 } } //歸併排序 void merg(std::vector<int>& ll, std::vector<int>& tmpArray, int leftPos, int rightPos, int rightEnd) { auto leftEnd = rightPos - 1; auto tmpPos = leftPos; auto numElements = rightEnd - leftPos + 1; while (leftPos <= leftEnd && rightPos <= rightEnd) { if (ll[leftPos] <= ll[rightPos]) { tmpArray[tmpPos++] = ll[leftPos++]; } else { tmpArray[tmpPos++] = ll[rightPos++]; } } while (leftPos <= leftEnd) { tmpArray[tmpPos++] = ll[leftPos++]; } while (rightPos <= rightEnd) { tmpArray[tmpPos++] = ll[rightPos++]; } for (auto i = 0; i < numElements; i++, rightEnd--) { ll[rightEnd] = tmpArray[rightEnd]; } } //分治策略, 數組切成兩半,而後對兩個數組進行排序以後, 而後再合併 void mergSortDriver(std::vector<int>& ll, std::vector<int>& tmpArray, int left, int right) { if (left < right) { auto center = (left + right) / 2; mergSortDriver(ll, tmpArray, left, center); mergSortDriver(ll, tmpArray, center + 1, right); merg(ll, tmpArray, left, center + 1, right); } } void mergSort(std::vector<int>& ll) { std::vector<int> tmpArray(ll.size()); mergSortDriver(ll, tmpArray, 0, ll.size() - 1); } //快速排序 //選擇一個樞紐元, 而後確保左邊的元素小於樞紐元, 右邊的元素大於樞紐元, 而後分別對左右兩邊分別進行快排 int median3(std::vector<int>& a, int left, int right) { auto center = (left + right) / 2; if (a[center] < a[left]) { std::swap(a[left], a[center]); } if (a[right] < a[left]) { std::swap(a[left], a[right]); } if (a[right]<a[center]) { std::swap(a[center], a[right]); } std::swap(a[center], a[right - 1]); return a[right - 1]; } void quickSort(std::vector<int>& ll, int left, int right) { if (left + 10 <= right) { auto pivot = median3(ll, left, right); auto i = left, j = right - 1; while (true) { while (ll[++i] < pivot) {} while (pivot < ll[--j]) {} if (i<j) { std::swap(ll[i], ll[j]); } else { break; } } std::swap(ll[i], ll[right - 1]); quickSort(ll, left, i - 1); quickSort(ll, i + 1, right); } else { insertSort(ll, left, right); } } void sort_test() { if (true) { auto l1 = generateIntList(); auto l2 = l1; std::cout << "insertSort>>>>" << '\n'; std::cout << "before: "; showIntList(l1); insertSort(l1); std::cout << "l1: "; showIntList(l1); std::sort(l2.begin(), l2.end()); std::cout << "l2: "; showIntList(l2); //用標準庫的sort函數的結果來進行測試驗證 assert(l1 == l2); } if (true) { auto l1 = generateIntList(); auto l2 = l1; std::cout << "shellSort>>>>" << '\n'; std::cout << "before: "; showIntList(l1); shellSort(l1); std::cout << "l1: "; showIntList(l1); std::sort(l2.begin(), l2.end()); std::cout << "l2: "; showIntList(l2); //用標準庫的sort函數的結果來進行測試驗證 assert(l1 == l2); } if (true) { auto l1 = generateIntList(); auto l2 = l1; std::cout << "heapSort>>>>" << '\n'; std::cout << "before: "; showIntList(l1); heapSort(l1); std::cout << "l1: "; showIntList(l1); std::sort(l2.begin(), l2.end()); std::cout << "l2: "; showIntList(l2); //用標準庫的sort函數的結果來進行測試驗證 assert(l1 == l2); } if (true) { auto l1 = generateIntList(); auto l2 = l1; std::cout << "mergSort>>>>" << '\n'; std::cout << "before: "; showIntList(l1); mergSort(l1); std::cout << "l1: "; showIntList(l1); std::sort(l2.begin(), l2.end()); std::cout << "l2: "; showIntList(l2); //用標準庫的sort函數的結果來進行測試驗證 assert(l1 == l2); } if (true) { auto l1 = generateIntList(30); auto l2 = l1; std::cout << "quickSort>>>>" << '\n'; std::cout << "before: "; showIntList(l1); quickSort(l1, 0, l1.size() - 1); std::cout << "l1: "; showIntList(l1); std::sort(l2.begin(), l2.end()); std::cout << "l2: "; showIntList(l2); //用標準庫的sort函數的結果來進行測試驗證 assert(l1 == l2); } }