冒泡排序和快速排序
2017-08-07 14:43
141 查看
冒泡排序:
快速排序:
随机快速排序:在快速排序的基础上,只有一处改动,就是在Partition时,随机选择了一个元素作为target,仅此而已。
双路快速排序:对于含有大量重复元素的数组,随机快排Partition的左右部分长度可能相差很大,使用双路快排能够尽量维护Partition后左右部分长度相当,从而提高效率。
三路快速排序:Partition操作不再只分成两部分了,而是分成三部分,小于target的部分,等于target的部分,大于target的部分。
#include <iostream> #include <vector> using namespace std; // 冒泡排序 void bubbleSort(vector<int>& arr){ if(arr.empty()) return; // 外循环n-1次 // 循环一次的结果:将最大的元素通过多次交换挪至最后的位置 for(int i = 1; i < arr.size(); ++i){ for(int j = 0; j < arr.size()-i; ++j){ if(arr[j] > arr[j+1]) swap(arr[j], arr[j+1]); } } }
快速排序:
#include <iostream> #include <vector> using namespace std; // [l,r]左闭右闭区间进行Partition操作 int _partition(vector<int>& arr, int l, int r){ // 选择最左侧元素作为分割点 int target = arr[l]; // arr[l+1...j] < target ; arr[j+1...i) >= target // j是左半部分的最后一个元素的索引 int j = l; for(int i = l + 1; i <= r; ++i) if(arr[i] < target){ ++j; swap(arr[j], arr[i]); } // 最后将target与左半部分最后一个元素互换 swap(arr[l], arr[j]); return j; } // 对arr[l...r]部分进行快速排序 void _quickSort(vector<int>& arr, int l, int r){ if(l >= r) return; int p = _partition(arr, l, r); _quickSort(arr, l, p-1); _quickSort(arr, p+1, r); } void quickSort(vector<int>& arr){ // arr.size() 是size_t类型,当arr.size() == 0时,arr.size()-1可不是-1哦 if(arr.empty()) return; _quickSort(arr, 0, arr.size()-1); } int main(){ // 测试 vector<int> arr{3,9,1,2,4,3,2,7}; quickSort(arr); for(auto c : arr) cout << c << " "; cout << endl; return 0; }
随机快速排序:在快速排序的基础上,只有一处改动,就是在Partition时,随机选择了一个元素作为target,仅此而已。
#include <iostream> #include <vector> #include <algorithm> #include <ctime> using namespace std; // [l,r]左闭右闭区间进行Partition操作 int _partition(vector<int>& arr, int l, int r){ // 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot swap(arr[l], arr[rand()%(r-l+1)+l]); // 选择最左侧元素作为分割点 int target = arr[l]; // arr[l+1...j] < target ; arr[j+1...i) >= target // j是左半部分的最后一个元素的索引 int j = l; for(int i = l + 1; i <= r; ++i) if(arr[i] < target){ ++j; swap(arr[j], arr[i]); } // 最后将target与左半部分最后一个元素互换 swap(arr[l], arr[j]); return j; } // 对arr[l...r]部分进行快速排序 void _quickSort(vector<int>& arr, int l, int r){ if(l >= r) return; int p = _partition(arr, l, r); _quickSort(arr, l, p-1); _quickSort(arr, p+1, r); } void quickSort(vector<int>& arr){ // arr.size() 是size_t类型,当arr.size() == 0时,arr.size()-1可不是-1哦 if(arr.empty()) return; srand(time(NULL)); _quickSort(arr, 0, arr.size()-1); } int main(){ vector<int> arr{3,9,1,2,4,99,23,12,8} 4000 ; quickSort(arr); for(auto c : arr) cout << c << " "; cout << endl; return 0; }
双路快速排序:对于含有大量重复元素的数组,随机快排Partition的左右部分长度可能相差很大,使用双路快排能够尽量维护Partition后左右部分长度相当,从而提高效率。
#include <iostream> #include <vector> #include <algorithm> #include <ctime> using namespace std; int _partition(vector<int>& arr, int l, int r){ // 随机 swap( arr[l] , arr[rand()%(r-l+1)+l] ); int target = arr[l]; // arr[l+1...i) <= target; arr(j...r] >= target int i = l + 1; int j = r; while( true ){ // 注意边界, arr[i] < target, 不能是arr[i] <= target // 为了保持Partition后两部分长度不至于相差太大 while( i <= r && arr[i] < target ) i ++; // 注意边界, arr[j] > target, 不能是arr[j] >= target while(j >= l+1 && arr[j] > target) --j; if(i > j) break; swap(arr[i], arr[j]); ++i; --j; } swap(arr[l], arr[j]); return j; } // 对arr[l...r]部分进行快速排序 void _quickSort(vector<int>& arr, int l, int r){ if(l >= r) return; int p = _partition(arr, l, r); _quickSort(arr, l, p-1); _quickSort(arr, p+1, r); } void quickSort(vector<int>& arr){ // arr.size() 是size_t类型,当arr.size() == 0时,arr.size()-1可不是-1哦 if(arr.empty()) return; srand(time(NULL)); _quickSort(arr, 0, arr.size()-1); } int main(){ srand(time(NULL)); vector<int> arr{3,9,1,2,8,8,8,4,99,23,12,8,8,8,8,8,8}; quickSort(arr); for(auto c : arr) cout << c << " "; cout << endl; return 0; }
三路快速排序:Partition操作不再只分成两部分了,而是分成三部分,小于target的部分,等于target的部分,大于target的部分。
#include <iostream> #include <algorithm> #include <ctime> #include <vector> using namespace std; void _quickSort3Ways(vector<int>& arr, int l, int r){ if(l >= r) return; swap(arr[l], arr[rand()%(r-l+1)+l]); int target = arr[l]; // l:left, le:left-end, r:right, rs:right-start int le = l; // arr[l+1...le] < target int rs = r + 1; // arr[rs...r] > target int i = l+1; // arr[le+1...rs) == target while(i < rs){ if(arr[i] < target){ swap(arr[i], arr[le+1]); ++i; ++le; } else if(arr[i] > target){ swap(arr[i], arr[rs-1]); --rs; } else{ // arr[i] == target部分 ++i; } } swap(arr[l], arr[le]); _quickSort3Ways(arr, l, le-1); _quickSort3Ways(arr, rs, r); } void quickSort3Ways(vector<int>& arr){ srand(time(NULL)); if(arr.empty()) return; _quickSort3Ways(arr, 0, arr.size()-1); } int main(){ vector<int> arr{3,9,1,2,8,8,8,4,99,23,12,8,8,8,8,8,8}; quickSort3Ways(arr); for(auto c : arr) cout << c << " "; cout << endl; return 0; }
相关文章推荐
- Java中快速排序,冒泡排序和选择排序的实现
- 常见排序集合(冒泡排序,选择排序,直接插入排序,二分插入排序,快速排序,希尔排序,归并排序)
- 冒泡排序,选择排序,快速排序的代码
- 常用排序算法(快速排序,冒泡排序,最大公约数,Fibonacci )【原创】
- 冒泡排序,熙儿排序,快速排序,插入排序,堆排序,基数排序性能对比
- 冒泡排序,快速排序,简单选择排序
- 快速排序、插入排序、选择排序和冒泡排序的实现
- Python实现冒泡排序、选择排序、插入排序、快速排序、归并排序、二分法查找算法(基于《算法导论》伪代码)
- 浅谈C++之冒泡排序、希尔排序、快速排序、插入排序、堆排序、基数排序性能对比分析
- 八大排序算法总结之一(冒泡排序,快速排序,直接插入排序,希尔排序)
- 冒泡排序,快速排序,堆排序比较
- [汇编版]冒泡排序、快速排序、堆排序
- 常用排序算法之交换排序 ( 冒泡排序、快速排序 )
- Java 基础 快速实现 冒泡排序 和 选择排序
- 算法学习 - 归并排序,快速排序,冒泡排序
- php 冒泡排序 快速排序
- 1.交换排序:冒泡排序和快速排序
- 排序算法(快速排序,冒泡排序,插入排序,堆排序)
- java数组排序示例(冒泡排序、快速排序、希尔排序、选择排序)
- 插入排序、冒泡排序、选择排序、希尔排序、快速排序、归并排序、堆排序和LST基数排序——JAVA实现