qizongshuai 2017-05-25
基本思想:将一个值插入到已经排好序中的相应位置。
void InsertSort(std::vector<int>& arr) { for (size_t i = 1; i < arr.size(); i++) { if (arr[i] < arr[i-1]) { size_t k = i; int val = arr[k]; //保存下自己 arr[k] = arr[i-1];//向后移一位 while (val < arr[k-1] && k > 0) { arr[k] = arr[k-1]; k--; } arr[k] = val; printArray(i, arr); } } }
基本思想:两两比较相邻纪录的关键字,如果是反序的则进行交换。
// 普通排序 void BubbleSort(std::vector<int>& arr) { size_t len = arr.size(); for (size_t i = 0; i < len; i++) { //内层的每一次循环,都会将最大的数推向数组高层,也就是说i代表了高层中已经排好序的个数 for (int j = 1; j < len-i; j++) { if (arr[j-1] > arr[j]) { //两两比较 std::swap(arr[j-1], arr[j]); } } printArray(i, arr); } } // 设置标记位,如果一次循环中没有移位,那么则表明接下来的值的顺序已经排好了 void BubbleSort2(std::vector<int>& arr) { size_t len = arr.size(); bool flag = true; size_t k = len; while (flag) { flag = false; for (int j = 1; j < k; j++) { if (arr[j-1] > arr[j]) { std::swap(arr[j-1], arr[j]); flag = true; } } k --; } } // 设置上次移动的位置,表明上次之前的位置已经拍好了序,接下来只需要排上次位置之前的即可 void BubbleSort3(std::vector<int>& arr) { size_t len = arr.size(); size_t flag = len; while (flag > 0) { size_t k = flag; flag = 0; for (size_t j = 1; j < k; j++) { if (arr[j-1] > arr[j]) { //两两比较 std::swap(arr[j-1], arr[j]); flag = j; } } } } // 双向冒泡排序,在之前的排序中,每次的内层循环只能找出一个最大值或者最小值 // 现在双向排序后同时找出一个最大值和最小值 void BubbleSort4(std::vector<int>& arr) { size_t low = 0, high = arr.size() - 1; while (low < high) { for (size_t i = low; i < high; i++) { if (arr[i] > arr[i + 1]) { std::swap(arr[i], arr[i + 1]); } } high--; for (size_t i = high; i > low; i--) { if (arr[i - 1] > arr[i]) { std::swap(arr[i - 1], arr[i]); } } low++; } }
基本思想:从一个数组中选择一个最小(或者最大)的值和第一个位置进行交换,接着选择次的值和第二个位置交换,以此类推。
void SelectSort(std::vector<int>& arr) { // 每次从指定的数组间隔中选择一个最小的 auto selectMin = [&](size_t start) { size_t k = start; for (size_t i = start+1; i < arr.size(); i++) { if (arr[i] < arr[k]) { k = i; } } std::cout << "min:" << arr[k] << std::endl; return k; }; size_t len = arr.size(); for (size_t i = 0; i < len; i++) { size_t idx = selectMin(i); if (idx != i) { std::swap(arr[idx], arr[i]); } printArray(i, arr); } }
基本思想:
int partition(std::vector<int>& arr, int low, int high) { int key = arr[low]; while (low < high) { while (low < high && arr[high] >= key) { high--; } std::swap(arr[low], arr[high]); while (low < high && arr[low] <= arr[high]) { low++; } std::swap(arr[low], arr[high]); } printArray(0, arr); return low; } void QuickSort(std::vector<int>& arr, int low, int high) { if (low < high) { int key = partition(arr, low, high); QuickSort(arr, low, key); QuickSort(arr, key+1, high); } } void printArray(size_t idx, const std::vector<int>& arr) { if (arr.empty()) { std::cout << "没有数据" << std::endl; return ; } std::cout << "第" << idx + 1 << "趟:"; for (int i = 0; i < arr.size(); i++) { std::cout << arr[i] << " "; } std::cout << std::endl; }
基本思想:首先创建最小堆,在取出堆顶的元素之后进行调整堆,将对堆顶移到数组后面从而实现删除的意思,使其依旧是一个最小堆,直到堆中的元素都取完。
void buidlHeap(std::vector<int>& arr) { int len = arr.size(); // 这里根据父亲结点(最多为数组一半的位置)进行调整 for (int idx = len/2; idx >= 0; idx--) { adjustHeap(arr, idx, len); } } // heapsize是用来控制堆的大小 void adjustHeap(std::vector<int>& arr, int idx, int heapsize) { int left_idx = idx * 2 + 1, right_idx = left_idx+1; int min_idx = idx; // 找结点idx中左子结点和右子结点较小的 if (left_idx < heapsize && arr[idx] > arr[left_idx]) { min_idx = left_idx; } if (right_idx < heapsize && arr[min_idx] > arr[right_idx]) { min_idx = right_idx; } if (min_idx != idx) { std::swap(arr[min_idx], arr[idx]); adjustHeap(arr, min_idx, heapsize); } } void HeapSort(std::vector<int>& arr) { buidlHeap(arr); printArray(0, arr); int len = arr.size(); // 每次取出堆顶后,把堆顶置换到后面,通过heapsize删除该元素 for (int i = len-1; i >= 0; i--) { std::cout << arr[0] << std::endl; std::swap(arr[0], arr[i]); adjustHeap(arr, 0, i); } }
void printArray(size_t idx, const std::vector<int>& arr) { if (arr.empty()) { std::cout << "没有数据" << std::endl; return ; } std::cout << "第" << idx + 1 << "趟:"; for (int i = 0; i < arr.size(); i++) { std::cout << arr[i] << " "; } std::cout << std::endl; }
要知道时间复杂度只是描述一个增长趋势,复杂度为O的排序算法执行时间不一定比复杂度为O长,因为在计算O时省略了系数、常数、低阶。实际上,在对小规模数据进行排序时,n2的值实际比 knlogn+c还要小。