快速排序的应用

来源:互联网 发布:linux 同时连接内外网 编辑:程序博客网 时间:2024/06/05 04:24

1、把序列中的正负数分开

举例:

序列:0,2,-1,4,-2,-3,6,7,-9,10

处理好的序列:-9 -3 -1 -2 4 2 6 7 0 10

注意:

仅仅把正负数分开就好,正数和负数里面不要求次序

不要求排序,这里遍历一遍序列就可以了,时间复杂度为O(n)

//应用一:把序列中的正负数分开算法#include <iostream>using namespace std;const int len = 10;void Divide(int arr[],int n);int main(){int arr[len]={0,2,-1,4,-2,-3,6,7,-9,10};//int arr[len]={1,2,1,4,2,3,6,7,9,10};Divide(arr,len);for (int i=0;i<len;i++){cout<<arr[i]<<" ";}system("pause");}/*进行一次快速排序即可*/void Divide(int arr[],int n){int temp;int low=0;int high = n-1;while (low<high){while (low<high && arr[low]<0){low++;}while (low < high && arr[high]>=0){high--;}if (low < high)//满足此式时,表示遇到了arr[low]指向正数,但是arr[high]指向负数的情况,这时需要互换元素{temp = arr[low];arr[low]=arr[high];arr[high]=temp;//互换后,low和high位置已经处理完毕,这时下标要往前移动一位---不要忘了啊low++;high--;}}}

2、查找第j小的元素

//应用二:查找第j小的元素#include <iostream>using namespace std;const int len =10000;template<class T>T QSort(T arr[],int n,int j);template<class T>int Partition(T arr[],int low,int high);int main(){int arr[len];for (int i=0;i<len;i++){arr[i]=rand()%100;}cout<<"第"<<7<<"个数为:"<<QSort(arr,len,6)<<endl;system("pause");return 0;}template<class T>T QSort(T arr[],int n,int j){int low = 0;int high = n-1;int keyLoc = Partition(arr,low,high);while (keyLoc != j){if (keyLoc > j){keyLoc = Partition(arr,low,keyLoc-1);}else{keyLoc = Partition(arr,keyLoc+1,high);}}return arr[j];}template<class T>int Partition(T arr[],int low,int high){T key = arr[low];while (low < high){while (low < high && arr[high] >= key){high--;}arr[low] = arr[high];while (low<high && key >= arr[low]){low++;}arr[high] = arr[low];}arr[low] = key;return low;}

3、荷兰国旗

//应用三:荷兰国旗//思想:可以视为数组的排序问题,这个数组可以分为 前部 中部和后部,当前边和后面拍好后,数组自动排好了//具体思路://前提:使用j进行对数组进行遍历,i指向红色区,k指向蓝色区--(j左边和k右边的元素全被处理过)//效果:0 - i-1:红色  i - k-1:白色  k - n-1:蓝色//1、j遍历到的位置为1(红)时,说明它一定在前部,//则直接和i进行交换即可,这里i始终指向以确定白色位置的下一位,并且i和j均想前走一步(++)//2、j遍历到的位置为2(白)时,说明它一定在中部,//则该元素不动,j向先走一步,处理下一个位置//3、j遍历到的位置为3(蓝)时,说明它一定在后部,//则直接和k进行交换,这里k始终指向确定是蓝色位置的前一位(倒着走的),这时k应--,但是此时j不能向前走,//刚换过来的元素是还没处理过的,这时j往前走,就会把该元素忽略(j左边和k右边的元素全被处理过)//这里一直担心的问题是,出现“22211”时怎么处理:见2时往前走,见到第一个1时,应该和第一个2交换,这时1就和2换位置了,刚刚可以满足题意#include <iostream>using namespace  std;const int len = 10;void FlagAdjust(int arr[],int n);void Show(int arr[],int n);int main(){int arr[len];for (int i=0;i<len;i++){arr[i]=rand()%3 + 1;}Show(arr,len);FlagAdjust(arr,len);Show(arr,len);system("pause");return 1;}void FlagAdjust(int arr[],int n){int i=0;int j=0;int k=n-1;int temp;while (j<k){if (arr[j]==1)//红色{temp =arr[i];arr[i]=arr[j];arr[j]=temp;i++;j++;}else if (arr[j]==2)//2代表白色{j++;}else//3代表蓝色{temp=arr[j];arr[j]=arr[k];arr[k]=temp;k--;}}}void Show(int arr[],int n){for (int i=0;i<len;i++){switch (arr[i]){case 1:cout<<"红";break;case 2:cout<<"白";break;case 3:cout<<"蓝";break;}}cout<<endl;}

4、快排的非递归程序,这里是固定选择枢轴的版本

/*快排的非递归代码*/#include <iostream>using namespace std;const int len = 10;struct node{int low;int high;};void QSort(int arr[],int n);int main(){int arr[len];for (int i=0;i<len;i++){arr[i]=rand()%100;}//排序前结果for (int i=0;i<len;i++){cout<<arr[i]<<" ";}cout<<endl;//快速排序QSort(arr,len);//排序后结果for (int i=0;i<len;i++){cout<<arr[i]<<" ";}cout<<endl;system("pause");return 1;}void QSort(int arr[],int n){int top=-1;struct node stack[len];int low =0;int high=0;top++;stack[top].low = 0;stack[top].high = n-1;while (top>-1){//出栈low = stack[top].low;high = stack[top].high;top--;while (low < high){//这里引入first和low的原因:low和high在下面的一次快排中会发生变化,//而根据最终枢轴位置还要把原数据分成两段,这时需要记录本次待排序数据长度的首尾下标int first = low;int last = high;//一次快排int key = arr[low];while (low<high){while (high > low && arr[high] > key){high--;}arr[low]=arr[high];while (high > low && arr[low] < key){low++;}arr[high] = arr[low];}arr[low]=key;//枢轴把数据分成两段,这时需要把这两段待排序的两下标都放入栈中,之后进行依次出栈进行排序//枢轴左半段入栈top++;stack[top].low = first;stack[top].high = low -1;//枢轴右半段入栈top++;stack[top].low = low+1;stack[top].high = last;}}}



 


 

原创粉丝点击