平均时间复杂度:O(nlogn)
最坏情况下的是:O(n^2) – 数列顺逆序
递归 – 单边循环法
#include <iostream>
using namespace std;
// partition()实现元素交换
int partition(int arr[], int startIndex,int endIndex) {
int temp = 0;
// pivot作为基准值(数列区域分割线)
// 临时存储arr[startIndex]的值
int pivot = arr[startIndex];
// mark:小于基准值的边界线
int mark = startIndex;
for(int i = startIndex;i <= endIndex;i++){
// 小于基准值则
// 1.小于基准值的边界区域(mark)扩增1
// 2.将当前元素(小于基准值的元素)与mark指代元素交换位置
if(arr[i] < pivot){
mark++;
temp = arr[i];
arr[i] = arr[mark];
arr[mark] = temp;
}
}
// 基准值归位
// 每轮交换完毕后,将mark元素与初始位pivot元素交换
// 使分割线 pivot在对应位置(小于|pivot|大于的)
arr[startIndex] = arr[mark];
arr[mark] = pivot;
// 最后返回分割线位置下标
return mark;
}
void quickSort(int arr[], int startIndex,int endIndex,int len) {
// 递归结束条件:startIndex >= endIndex
// 直到不可拆分为止
if(startIndex > endIndex)
return;
// 非法输入判断,防止数组越界
if(startIndex < 0 || endIndex >=len){
cout << "argc error,array bound"<<endl;
return;
}
// 得到基准元素位置
int pivotIndex = partition(arr,startIndex,endIndex);
// 根据基准元素,分成两部分进行递归排序
quickSort(arr,startIndex,pivotIndex-1,len);
quickSort(arr,pivotIndex+1,endIndex,len);
}
void printArr(int a[], int len) {
for(int i = 0;i< len; i++){
cout << a[i] << " ";
}
cout <<endl;
}
int main() {
int arr[] ={4,7,3,5,6,2,8,1};
int len = sizeof(arr)/sizeof(int);
int endIndex = len -1;
cout << "排序前:";printArr(arr,len);
quickSort(arr, 0, endIndex,len);
cout << "排序后:";printArr(arr,len);
}
非递归实现
- 原本的递归实现转化成一个栈的实现
- 用栈保存每一个待排序子串的【首|尾】的【元素下标】,下一次while循环时取出这个范围,对这段子序列进行partition操作
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
void print(const vector<int>& array)
{
for(auto val:array)
cout<<val<<" ";
cout<<endl;
}
int partition(vector<int>&arr,int start,int end)
{
int temp = 0;
int left = start;
int right = end;
int pivot = arr[start];
while(left!=right){
// 控制right 指针比较并左移
while(left < right && arr[right] > pivot)
right--;
// 控制left指针比较并右移,注意左分区取值范围“ <= ”
while(left < right && arr[left] <= pivot)
left++;
// 交换left和right 指针所指向的元素
if(left < right){
temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
}
}
//pivot 和指针重合点交换
arr[start] = arr[left];
arr[left] = pivot;
return left;
}
//辅助函数
void qsortHelp(vector<int>& array,int start, int end)
{
stack<int>temp;
//先把区间入栈,保证栈内不为空
temp.push(end); // push 压栈存入end
temp.push(start); // push 压栈存入start
while(!temp.empty()){
start = temp.top(); // 获取栈顶元素(不弹栈) start = 0;
temp.pop(); // 弹出 start
end = temp.top(); // 获取栈顶元素(不弹栈) end = len-1;
temp.pop(); // 弹出 end
if(start < end){
//根据此时的左右区间,选出中间的基准值key
int div = partition(array,start,end);
// 左分区存在:[start,div-1]
if(div -1 > start){
temp.push(div-1);
temp.push(start);
}
// 右分区存在:[div+1,end]
if(div + 1 < end){
temp.push(end);
temp.push(div+1);
}
}
}
}
//非递归排序入口函数
void quickSort(vector<int>& arr)
{
if(arr.empty())
return;
int len = arr.size();
// printf("len = %d\n",len);
qsortHelp(arr,0,len-1);
}
int main()
{
vector<int>array{1,5,2,4,0,3,8,9,7,6};
cout<<"排序前: ";print(array);
quickSort(array);
cout<<"排序后: ";print(array);
return 0;
}