// 此版本为调整优化好的快速排序算法实现。 # include <iostream> # include <vector> using namespace std; int Partition(vector<int> &arr, int low, int high) { int pivot; // 划分后基准记录的位置 int pivotkey = arr[low]; // 用区间的第一个值作为基准,也可以采用其他方式,比如三数取中 while (low < high) { while (low < high && arr[high] >= pivotkey) // 先从右向左扫描 high--; if (low < high) // 每次必须有判断,因为有可能在此时出现low>high的情况 arr[low++] = arr[high]; while (low < high && arr[low] <= pivotkey) // 再从左向右扫描 low++; if(low < high) arr[high--] = arr[low]; } pivot = low; // 找出基准位置 arr[pivot] = pivotkey; // 基准位置定位 return pivot; } // 典型的分治法的思想 void quicksort(vector<int> &arr, int low, int high) { if (low < high) // 仅当区间长度大于 1 时才排序 { int pivot = Partition(arr, low, high); // 分解,找出基准 quicksort(arr, low, pivot-1); // 递归求解左子区间 quicksort(arr, pivot + 1, high); // 递归求解右子区间 } } int main () { vector<int> arr; int temp; while (cin >> temp) { arr.push_back(temp); // 将数存入数组 } quicksort(arr, 0, arr.size() - 1); for(auto i : arr) cout << i << endl; return 0; }
// 优化的冒泡算法实现 # include <iostream> # include <vector> using namespace std; void BubbleSort(vector<int> &arr) { int i , j, temp,len; len = arr.size(); for (i = 0; i < len - 1; i++) // 外层循环控制无序区的终点位置 { bool flag = true; for (j = len - 1; j > i; j--) //内层控制每次比较的位置 { if (arr[j] < arr[j - 1]) { temp = arr[j]; arr[j] = arr[j -1]; arr[j - 1] = temp; flag = false; } } if (flag) break; } } int main() { vector<int> arr; int temp; while (cin >> temp) { arr.push_back(temp); // 将数存入数组 } BubbleSort(arr); cout <<"after sort: "<< endl; for(auto i : arr) cout << i << endl; return 0; }
// 简单选择算法实现,相比于冒泡排序,最大的特点是数据交换移动次数较少,找到合适的关键字(最小值的位置)再交换 # include <iostream> # include <vector> using namespace std; void SelectSort(vector<int> &arr) { int i , j, temp,len, minindex; len = arr.size(); for (i = 0; i < len - 1; i++) // 外层循环控制无序区的起点位置 { minindex = i; for (j = i + 1; j <= len ; j++) //内层控制每次比较的位置,注意范围控制 { if (arr[j] < arr[minindex]) minindex = j; } if (minindex != i) // 若有比当前值还小的最小值,则将最小值放到无序区的起点位置 { temp = arr[minindex]; arr[minindex] = arr[i]; arr[i] = temp; } } } int main() { vector<int> arr; int temp; while (cin >> temp) { arr.push_back(temp); // 将数存入数组 } SelectSort(arr); cout <<"after sort: "<< endl; for(auto i : arr) cout << i << endl; return 0; }
// 直接插入排序算法实现: 基本操作是讲一个记录插入到已经排好序的有序表汇总, // 从而得到 一个新的、记录数增1的有序表 // 时间复杂度: O(n^2) // author: SimplePaul # include <iostream> # include <vector> using namespace std; void InsertSort(vector<int> &arr) { int i , j, temp,len; len = arr.size(); for (i = 1; i <= len - 1; i++) // { if(arr[i] < arr[i-1]) // 若当前比前一个小,则需要交换,否则不交换 { temp = arr[i]; // 保存当前的值 for ( j = i - 1; arr[j] > temp && j >= 0; j--) // j>= 0的条件容易忘 { arr[j + 1] = arr[j]; // 记录后移,直到当前值比temp要小 } arr[j + 1] = temp; } } } int main() { vector<int> arr; int temp; while (cin >> temp) { arr.push_back(temp); // 将数存入数组 } InsertSort(arr); cout <<"after sort: "<< endl; for(auto i : arr) cout << i << endl; return 0; }
// 希尔排序算法实现: 希尔排序(Shell Sort)是插入排序的一种,它是针对直接插入排序算法的改进 // 该方法又称缩小增量排序,希尔排序实质上是一种分组插入方法。它的基本思想是:对于n个待排序的数列, //取一个小于n的整数gap(gap被称为步长)将待排序元素分成若干个组子序列,所有距离为gap的倍数的记录 //放在同一个组中;然后,对各组内的元素进行直接插入排序。 这一趟排序完成之后,每一个组的元素都是 //有序的。然后减小gap的值,并重复执行上述的分组和排序。重复这样的操作,当gap=1时,整个数列就是有序的。 // 相当于是 插入排序只是执行了希尔排序的gap=1的情况 // 时间复杂度: O(nlog(n))~O(n^2) ,不稳定排序 // author: SimplePaul # include <iostream> # include <vector> using namespace std; void ShellSort(vector<int> &arr) { int i , j, temp,len,gap; len = arr.size(); gap = len / 2; // 取增量 while (gap >= 1) { for (i = gap; i <= len - 1; i += gap) // 进行插入排序,相当于原来每次插入排序的间隔为1,现在为gap { if(arr[i] < arr[i - gap]) // 若当前比前一个(前一个指相差gap的前一个值)小,则需要交换,否则不交换 { temp = arr[i]; // 保存当前的值 for ( j = i - gap; arr[j] > temp && j >= 0; j -= gap) // j>= 0的条件容易忘 { arr[j + gap] = arr[j]; // 每次记录后移gap,直到当前值比temp要小 } arr[j + gap] = temp; } } gap /= 2; // 设置新的增量 } } int main() { vector<int> arr; int temp; while (cin >> temp) { arr.push_back(temp); // 将数存入数组 } ShellSort(arr); cout <<"after sort: "<< endl; for(auto i : arr) cout << i << endl; return 0; }
堆排序实现:参考源
// 堆排序实现:
// 复杂度: O(NlogN)
//堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法
#include <iostream> using namespace std; // 最大堆的向下调整算法 MaxHeapDown() // 数组实现的堆中,第N个结点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2) // 其中,N为数组下标索引值,如数组第一个数对应的N为0。 // 参数说明: // a: 待排序的数组 // start: 被下调节点的起始位置(一般为0,表示从第一个开始) // ends: 截止范围(一般为数组中最后一个元素的索引) void MaxHeapDown(int* a, int start, int ends) { int c = start; // 当前(current)节点的位置 int l = 2 * c + 1; // 左(left)孩子的位置 int tmp = a[c]; // 当前节点的大小 for (; l <= ends; c = l, l = 2*l + 1) { // l 是左孩子, l + 1 是右孩子 if ( l < ends && a[l] < a[l + 1]) l++; // 左右两个孩子中选择较大者 if (tmp >= a[l]) break; // 若当前节点的值比两个孩子中的大者还大 就结束循环 //若是需要交换则执行下面的步骤 a[c] = a[l]; a[l] = tmp; } } // 堆排序(从小到大): a : 待排数组; n: 数组的长度 void HeapSortAsc(int *a, int n) { int i, tmp; // 从(n/2 - 1) --> 0 顺序遍历,之后得到的数组实际上是一个最大二叉堆 // 即从第一个有孩子的节点开始遍历调整, for (i = n / 2 - 1; i >= 0; i--) // 相当于建好一个堆 MaxHeapDown(a, i, n - 1); //从最后一个元素开始对序列进行调整,直到第一个元素 for (i = n - 1; i > 0; i--) { // 交换a[0]和 a[i],交换后a[i]是数组中最大的 tmp = a[0]; a[0] = a[i]; a[i] = tmp; //再调整a[0>>>>i-1],使得其仍为一个最大堆 MaxHeapDown(a, 0, i - 1); } } int main() { int i; int a[] = {20,30,90,40,70,110,60,10,100,50,80}; int len = (sizeof(a) / (sizeof(a[0]))); cout << "before sort:"; for (i = 0; i < len; i++) { cout << a[i] << " "; } cout << endl; HeapSortAsc(a, len); cout << "after sort:"; for (i = 0; i < len; i++) { cout << a[i] << " "; } cout << endl; return 0; }
// 一个例子:寻找最小的K个数
归并排序:待更新。。。