【C++】快速排序
性能分析:
时间复杂度:O(n*log(n))
空间复杂度:O(log(n))
这里的时间复杂度其实是快速排序最好的时间复杂度,最坏的时间复杂度是O(n^2)
代码里补充的随机化快速排序的期望时间复杂度为:O(n*log(n))
快速排序的性能优于归并排序是因为常数项,即算法所需的固定时间量。
#include<iostream> #include<vector> #include<algorithm> #include<random> #include<ctime> using namespace std; int partition(vector<int>& data, int left, int right); void quick_sort(vector<int>& data, int left, int right); int main() { // 思想: // 在元素序列上直接操作; // 每次在无序序列中选取一个数,一般称之为中轴数, // 将元素序列分成两个部分,使得一部分的元素全都小于等于另一部分的所有元素; // 也就是说将序列分成小于等于中轴数和大于等于中轴数的两部分,使得中轴数变为有序; // 再递归的对分成的两部分进行划分操作,分到1的时候就是天然有序的了 // 改进的思想是:每次随机找一个中轴数,将其交换到末尾,然后再往下 vector<int> data = { 7,5,6,4 }; //获取序列元素个数 int length = data.size(); int left = 0; int right = 3; vector<int> result; quick_sort(data, left, right); for (int i = 0; i < length; i++) { cout << data.at(i) << " "; } } void quick_sort(vector<int>& data, int left, int right) { if (left < right) { //找到中轴数的索引 int index = partition(data, left, right); //以中轴数的索引为界递归的处理两个部分的序列 quick_sort(data, left, index - 1); quick_sort(data, index + 1, right); } } int partition(vector<int>& data, int left, int right) { // 找到中轴数的正确位置,同时将序列划分为两部分. // 中轴数有很多种取法,我们这里采用《算法导论》里的选取方法,即取序列最后一个元素. int key = data.at(right); // 此处设置两个索引i和j,区间[left,i]为小于中轴数的序列, // 区间[j,right-1]为大于中轴数的序列. /*这里有一种优化的方法,就是这个中轴数随机的找,然后交换到末尾,再往下执行*/ /* default_random_engine e(time(0)); //时间引擎 uniform_int_distribution<signed> u(left, right); int key = u(e); int tem = data.at(key); data.at(key) = data.at(right); data.at(right) = tem; int ave = data.at(right); */ int i = left - 1; for (int j = left; j < right; j++)//循环判断操作除了最右边基准值外的其他元素 { if (data.at(j) <= key) { // 大于中轴数的元素让它继续待在[j,right-1]区间什么也不做; // 小于中轴数的元素全部从[j,right-1]区间放到[left,i]区间去. ++i; int temp = data.at(i); data.at(i) = data.at(j); data.at(j) = temp; } } // 此时中轴数的正确位置应该在i+1,将其归位. // 思考为什么是i+1而不是i. int temp = data.at(i + 1); data.at(i + 1) = data.at(right); data.at(right) = temp; // 返回中轴数的正确索引. return i + 1; }
另一种,实现动态输入:
#include<iostream> #include<vector> using namespace std; void quick_sort(vector<int>& data, int left, int right) { if (left >= right) { return; } // 否则就开始在原数组上选区基准值进行交换 int key = data[right]; // 选区最后一个数 int i = left - 1; for (int j = left; j < right; j++) { if (data[j] <= key) { i++; swap(data[i], data[j]); } } // 将基准值放到i+1的位置 swap(data[i + 1], data[right]); // i+1就是分界点 int index = i + 1; quick_sort(data, left, index - 1); quick_sort(data, index + 1, right); } int main() { vector<int> data; // 输入要排序的数列 int n, d; cin >> n; // 输入数列大小 while (n-- && cin >> d) // 循环输入 { data.push_back(d); } int left = 0; int right = data.size() - 1; quick_sort(data, left, right); for (int i = 0; i <= right; i++) { cout << data[i] << ' '; } cout << endl; return 0; }