快速排序
来源:互联网 发布:提成算法 编辑:程序博客网 时间:2024/06/06 06:44
快速排序算法是一种划分交换的方法,它采用分治法进行排序。
基本思想:取元素序列的某个元素作为基准,将序列划分成左右两个子序列,比这个元素大的或小的放到左边,相对小的或大的放右边,该基准元素则放到中间。然后对此子序列重复上面的方法,直到所有的元素都排在相应的位置。
大体图解
这里我们就可以看到这完全是一个子问题,所以我们想到的第一种方法就是递归实现。
void QuickSort(int* a,int begin,int end){ assert(a); if (begin < end) { //partsort就是要实现每次某一段区间将怎样划分。 //int div = PartSort1(a, begin, end); //int div = PartSort2(a, begin, end); int div = PartSort3(a, begin, end); QuickSort(a, begin, div - 1); QuickSort(a, div + 1, end); }}
实现每一段区间的单趟排序
1.左右指针法
left,right表示一段区间的开始与结束,取a[right]作为基准key,当a[left]小于等于key时,left往后走,left++,当a[right]大于等于key时,right往前走,right–,否则,a[left]找一个比key大的,a[right]找一个比key小的时,进行交换,当left和right相遇时,就把key和这个位置的元素交换。
三数取中法
int Getmid(int* a, int left, int right){ int mid = left + (right - left) / 2; if (a[left] > a[right]) { if (a[left] > a[mid]) { if (a[mid] > a[right]) { return mid; } else { return right; } } else { return left; } } else { if (a[mid] < a[right]) { if (a[mid]>a[left]) { return mid; } else { return left; } } else { return right; } }}
int PartSort1(int* a, int begin, int end){ int left = begin; int right = end; int mid = Getmid(a, begin, end);//三数取中法优化,避免取到的基准太大或太小,影响效率。 swap(a[mid], a[end]);//将三数取中法取到的数放到最后 int key = a[right]; while (left < right)//left==right循环结束 { while(left < right && a[left] <= key) { left++; } while(left < right && a[right] >= key) { right--; } if (a[left] > a[right]) { swap(a[left], a[right]); } } swap(a[left], a[end]); return left;}
2.挖坑法
其思想和上一种方法大体相同,left,right同样是一段区间的结束和开始,先将a[right]作为第一个坑hole,并将该坑的元素保存,left++,找到一个比这个坑元素大的,放到这个坑里,这样left这个位置就是一个新坑,然后right–,找到一个hole小的,放到这个新坑里,当left和right相遇时,结束,将保存的第一个坑的元素放到这个位置。
int PartSort2(int* a, int begin, int end){ int left = begin; int right = end; int mid = Getmid(a, begin, end); int hole = a[end];//定义的一个坑 while (left < right) { while (left < right&&a[left] <= hole) { left++; } if (left < right)//循环可能是第一个条件不符合结束的,所以这里需要判断下 { swap(a[left], a[right--]); } while (left < right&&a[right] >= hole) { right--; } if (left < right) { swap(a[left++], a[right]); } } a[left] = hole; return left;}
3.前后指针法
定义cur=begin,prev=begin-1,取a[end]为key,cur小于等于key时,prev和cur都往后走,当cur大于key时,只cur++,当cur小于key并且++prev不等于cur时,交换cur,prev,这样小的在前面,大的在后面,当cur等于end时,key放到prev+1的位置。
int PartSort3(int* a, int begin, int end){ int cur = begin; int prev = begin - 1; int mid = Getmid(a, begin, end); swap(a[mid], a[end]); int key = a[end]; while (cur < end) { if (a[cur] < key&&++prev != cur) { swap(a[cur], a[prev]); } cur++; } swap(a[++prev], a[end]); return prev;}
非递归实现
要借助栈来保存每次排序的区间,取出来区间进行排序,然后又把新的区间压进去。
void QuickSortNoR(int* a, int begin, int end){ assert(a); stack<int> s; s.push(end); s.push(begin); while (!s.empty()) { int left = s.top(); s.pop(); int right = s.top(); s.pop(); if (left < right) { int div = PartSort2(a, left, right); s.push(div - 1); s.push(left); s.push(right); s.push(div + 1); } }}
快速排序是一种不稳定排序,对于排序码相同的元素,排序后可能会颠倒次序。它的时间复杂度是n*lgn。对于它的优化,三数取中法,还可以对小区间的优化,当划分到一定小的区间,不要再继续划分递归,毕竟递归的开销很大,用插入排序对这些小区间排序就行。
- 快速排序
- 快速排序
- 快速排序
- 快速排序!
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- 快速排序
- MFC 如何连接到SQL Server数据库
- CSS Reset 整理
- Bank Hacking (思维题)
- Modbus协议栈模型
- 联通规范双卡版本动态安装app 适配问题
- 快速排序
- 洛谷OJ
- 哈密顿绕行世界问题 ----dfs
- Android安全机制
- 关于使用MyBatis-Generator时自定义注解生成器的一些问题
- MSF使用MS17-010
- ionic——入门
- mvc+EF
- 利用梯度下降法实现线性回归的算法及matlab实现