排序算法(五)——快速排序
快速排序和归并排序一样都是基于递归求解,将问题划分成两个子问题,时间复杂度都是O(nlogn),不同的是快速排序的是基于元素与选定x的大小关系来划分。PS:一般我们选定序列第一个元素作为选定x。
示例序列:9 4 8 6 5 2 1 3 7 10
将9作为选定标准进行划分,小于等于9的都放在左边,大于9的都放在右边(考虑到会出现重复元素的情况)
划分子序列:设置两个指针low和high,分别指向两端。
从右边开始(注意一定要从右边开始)找到不满足>9的元素,第一遍找到7;
在从左边开始,找到不满足<=9的元素(等号必须出现在这里,因为最后当high==low的时候,要将9和list[high]进行交换,从而9的两边就能划分开了),没有找到,low和high都指向7,
将9和7进行交换,得到【7 4 8 6 5 2 1 3】 9 【10】,然后将9两边的两个子序列继续进行排序,当只有一个元素的时候,直接return,
依次递归下去。
示例代码:
#include <iostream> #include <ctime> using namespace std; void swap(int &a,int &b) { int temp=a; a=b; b=temp; } int Quick_sort_index(int list[],int begin,int end) { int low=begin,high=end; int num=list[begin]; while(low<high) { while(low<high&&list[high]>num) high--; while(low<high&&list[low]<=num) low++; if(list[low]!=list[high]) swap(list[low],list[high]); } if(list[high]!=num) swap(list[high],list[begin]); return high; } void Quick_sort(int list[],int begin,int end) { if(begin>=end) return; int index=Quick_sort_index(list,begin,end); Quick_sort(list,begin,index-1); Quick_sort(list,index+1,end); } int main() { int list[10]={1,23,345,12,6,56,45,444,23,46}; Quick_sort(list,0,9); for(int i=0;i<10;i++) cout<<list[i]<<" "; cout<<endl; system("pause"); }
另外递归和非递归(循环)的代码可参考:
https://www.cnblogs.com/ljy2013/p/4003412.html
pritation函数:
int Pritation(int* a, int left, int right) { if (a == NULL || left < 0 || right <= 0||left>=right) return -1; int priot = a[left]; int i = left, j = right; while (i < j) { while (i < j&&a[j] >= priot) j--; if(i<j) a[i]=a[j]; while (i < j&&a[i] <= priot) i++; if(i<j) a[j]=a[i]; } a[i] = priot; return i; }
递归代码:
void QuickSort(int *a, int left,int right) { if (a == NULL || left < 0 || right <= 0 || left>right) return; int k = Pritation(a, i, j); //下面是递归实现的代码 if (k > left) QuickSort(a, left, k - 1); if (k < right) QuickSort(a, k + 1, right); }
非递归代码:
void QuickSort(int *a, int left,int right) { if (a == NULL || left < 0 || right <= 0 || left>right) return; stack<int>temp; int i, j; //(注意保存顺序)先将初始状态的左右指针压栈 temp.push(right);//先存右指针 temp.push(left);//再存左指针 while (!temp.empty()) { i = temp.top();//先弹出左指针 temp.pop(); j = temp.top();//再弹出右指针 temp.pop(); if (i < j) { int k = Pritation(a, i, j); if (k > i) { temp.push(k - 1);//保存中间变量 temp.push(i); //保存中间变量 } if (j > k) { temp.push(j); temp.push(k + 1); } } } }