排序——快速排序
来源:互联网 发布:台达触摸屏编程软件3.0 编辑:程序博客网 时间:2024/05/18 00:48
终于有时间可以把快速排序,仔细的梳理一遍了。
快排 在实际中最常用的一种排序算法,速度快,效率高。就像名字一样,快速排序是最优秀的一种排序算法。
什么是快速排序?
快排的基本思想:快排采用的是分治(PS:分开治理)的思想。
过程是这样的:1、在一组数中找到一个基准值(key)
2、把这一组数分为小于key的一小组数,和大于key的另一小组数(按升序排列)
把小于key的一小组数放在key的左边 ,大于key的另一小组数放在key的右边
3、重复 1、 2步骤,直到各区间只有一个数。
下面用一组数来说明:
1 , 3 , 5 , 6 , 4 , 2
下面我们就用代码实现,通过代码在继续理解
<span style="font-family:Microsoft YaHei;font-size:14px;">//快速排序 int Partion(int *arr, size_t left,size_t right)//单次划分区间的左右索引{assert(arr);if (left < right){int key = arr[right];int begin = left;int end = right ;while (begin != end){while (begin < end && arr[begin] <= key)begin++;while (begin < end && arr[end] >= key)end--;if (begin < end)std::swap(arr[begin], arr[end]);}//把key的位置放到中间(实现划分区间)std::swap(arr[begin ], arr[right]);return begin ;}return -1;}void QuickSort(int arr[], size_t left , size_t right) //left right 是索引{assert(arr );if (left < right){int boundary = Partion(arr, left, right);QuickSort(arr, left, boundary - 1); //boundary-1 是左区间的上限QuickSort(arr, boundary + 1, right); //boundary+1 是右区间的下限}}</span>下面我将主要讲述,代码的单次划分区间流程:
其实,还有一种方法:挖坑法
具体是这样的:
<span style="font-size:14px;">//快排 -- 挖坑法int Partion1(int arr[], int left, int right){assert(arr);if (left < right){int key = arr[right];while (left != right){while (left < right && arr[left] <= key)left++;if (left < right)arr[right--] = arr[left];//right--while (left < right && arr[right] >= key)right--;if (left < right)arr[left++] = arr[right]; // left++}//最后一个坑arr[right] = key;}return right;}void QuickSort1(int arr[], const size_t left , const size_t right){assert(arr);if (left < right){int Boundary = Partion1(arr, left, right);QuickSort1(arr, left, Boundary - 1);QuickSort1(arr, Boundary + 1, right);}}</span>
这个挖坑法相比于第一种方法其实就是提前把数据搬移过去了。
用递归的方法就是使用了栈的思想, 那么我们来也自己创建议一个栈实现递归的思想。同时,就实现了递归和循环之间的转换
<span style="font-size:14px;">//快排---非递归--挖坑法int Partltion_4(int arr[], int left, int right){assert(arr);if (left < right){ //int mid = GetMid(arr, left, right); 后面怎么给值???int Key = arr[right];while (left != right){while (left < right && arr[left] <= Key)left++;if (left < right){arr[right--] = arr[left]; //填坑,right向前移动}while (left < right && arr[right] >= Key)right--;if (left < right){arr[left++] = arr[right]; //填坑,left向后移动}} arr[right] = Key; //////////////////////////////////!!! return right;}}void QuickSort_4(int arr[], int left, int right){assert(arr);stack<int> s;if (left < right){int boundary = Partltion_4(arr, left, right);if (boundary - 1 > left ){s.push(left);s.push(boundary - 1);}if (boundary + 1 < right){s.push(boundary + 1);s.push(right);}while (!s.empty()){int end = s.top();//结束位置s.pop();int begin = s.top();// 起始位置s.pop();int Boundary = Partltion_4(arr, begin, end); //多次划分if (Boundary - 1 > begin) //起始边界 由left-->begin{s.push(left);s.push(Boundary - 1);}if (Boundary + 1 < end) //结束边界 right -->end{s.push(Boundary + 1);s.push(right);}}}}</span>
int GetMid(int arr[], int left, int right) //返回的数组下标{assert(arr);int mid = left + ((right - left) >> 1);if (arr[left] < arr[right]){if (arr[mid] < arr[left]){return left;}else if (arr[mid] > arr[right]){return right;}else{return mid;}}else{if (arr[mid] < arr[right]){return right;}else if (arr[mid] > arr[left]){return left;}else{return mid;}}}
快排的时间复杂度
在最坏情况下,即数组已经有序或大致有序的情况下,每次划分只能减少一个元素,快速排序将不幸退化为冒泡排序,所以快速排序时间复杂度下界为O(nlogn),最坏情况为O(n^2)。
在实际应用中,快速排序的平均时间复杂度为O(nlogn)。
速排序空间复杂度为logn(因为递归调用了)
不稳定
0 0
- 排序—快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 排序——快速排序
- 交换排序—快速排序
- 排序算法—快速排序
- 排序算法—快速排序
- 内部排序—快速排序
- 排序方式—/冒泡排序/快速排序
- 排序3——堆排序,归并排序,快速排序
- 快速排序—java
- https 协议
- 异常处理(006)_常见的Java异常有哪些(运行时)
- 一、什么是动态网页、网站?
- Meshlab配置问题2
- 字符串 字符数组
- 排序——快速排序
- chrome 显示IP地址
- 从一个问题的多个算法看算法的优化
- spark资源参数调优
- Q65:滑动窗口的最大值
- cocos2dx-lua用sublime执行exe
- Java开发中的23种设计模式详解(转)
- 两个线程同时调用一个函数会出现什么情况?
- 红黑树