问题描述 :
对于顺序存储的线性表(假定顺序表非空),使用vector或数组,实现快速排序算法,并输出每趟的排序结果。
参考函数原型:(vector版本)
(1)//快速排序的实现(外壳)
template<class ElemType>
void QuickSort( vector<ElemType> &A );
(2)//快速排序的实现(递归)
template<class ElemType>
void QuickSort( vector<ElemType> &A, int low, int high);
(3)//划分函数(快速排序)
template<class ElemType>
int divide( vector<ElemType> &A, int low, int high );
输入说明 :
第一行:顺序表A的数据元素的数据类型标记(0:int,1:double,2:char,3:string)
第二行:待排序顺序表A的数据元素(数据元素之间以空格分隔)
输出说明 :
如第一行输入值为0、1、2、3之外的值,直接输出“err”
否则:
第一行:枢轴元素位置 枢轴元素
中间排序结果(数据元素之间以","分隔)
第二行:枢轴元素位置 枢轴元素
中间排序结果(数据元素之间以","分隔)
...
第n行:枢轴元素位置 枢轴元素
最终的排序结果(数据元素之间以","分隔)
注意:最终输出结果后有一空行
输入范例:
0
256 301 751 129 937 863 742 694 076 438
输出范例:
2 256
76,129,256,751,937,863,742,694,301,438
0 76
76,129,256,751,937,863,742,694,301,438
7 751
76,129,256,438,301,694,742,751,863,937
4 438
76,129,256,301,438,694,742,751,863,937
5 694
76,129,256,301,438,694,742,751,863,937
8 863
76,129,256,301,438,694,742,751,863,937
思路:
基本思想:
从待排序列中任取一个元素 (例如取第一个) 作为中心,所有比它小的元素一律前放,所有比它大的元素一律后放,形成左右两个子表;———>指向序列第一个元素的low和指向序列最后一个元素high交替/振荡式向中间逼近,先从high开始从后往前,如果指向的元素大于选定的中间元素,则high继续往前指,如果指向的元素小于指定的中间元素,则把该元素放到前面,并从换到low开始往后指。low同理,小于的就继续往后指,碰到大于的就把该元素移到后面,换到high开始。直到最后剩余一个空位,放置选定的中心元素。
然后再对左右各子表重新选择中心元素并依此规则调整,直到每个子表的元素只剩一个。此时便为有序序列了。(递归)
优点:因为每趟可以确定不止一个元素的位置,而且呈指数增加,所以特别快!
前提:顺序存储结构
时间效率:O(nlog2n) —因为每趟确定的元素呈指数增加
空间效率:O(log2n) —因为递归要用栈(存每层low,high和pivot)
稳定性:不稳定 —因为有跳跃式交换。* 快速排序的平均排序效率为O(nlog²n);但最坏情况下(例如天然有序)仍为O(n²)
代码实现:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <stdlib.h>
#include <cmath>
#include <vector>
#include <sstream> //用于ostringstream、istringstream、stringstream这三个类
#include<stack>
#include<vector>
#include<queue>
#include<list>
using namespace std;
template<class ElemType>
void createvector( vector<ElemType> &A )
{
ElemType tmp;
string temp;
getline(cin,temp);
stringstream input(temp); //输入流
while(input>>tmp)
A.push_back(tmp);
}
//划分函数(一次快速排序)
template<class ElemType>
int divide( vector<ElemType> &A, int low, int high )
{
ElemType temp=A[low]; //取首元素为枢轴,也可以用A[0]来做哨兵存放,效果一样
while(low<high){
while(low<high&&A[high]>temp) --high; //先从high开始,只要没碰到小于temp需要去移动的元素就一直走high
A[low]=A[high]; //初始的A[low]用temp存放,不怕覆盖,A[high]小移到前面去之后,原先位置相当于一个空位。
while(low<high&&A[low]<temp) ++low;//只要没碰到大于temp需要去移动的元素就一直走low
A[high]=A[low];//同理,执行完该步骤后,原先的low位置就相当于空位
}
A[high]=temp;//用A[low]也可以,因为退出while的条件就是high=low
cout<<low<<" "<<A[low]<<endl;
for(int k=0;k<A.size()-1;k++)
cout<<A[k]<<',';
cout<<A[A.size()-1]<<endl;
return high;//返回枢轴最终位置
}
//快速排序的实现(递归)
template<class ElemType>
void QuickSort( vector<ElemType> &A, int low, int high)
{
if(low<high){
int location=divide(A, low, high );
QuickSort(A, low, location-1 ); //下面两个是QuickSort函数,不再是divide函数了 不然无法实现递归!!!
QuickSort(A, location+1, high );
}
}
//快速排序的实现(外壳)
template<class ElemType>
void QuickSort( vector<ElemType> &A )
{
int low=0,high=A.size()-1; //若用A[0]为哨兵,则low从一开始
if(low==high)//只有一个元素
{
cout<<0<<" "<<A[low]<<endl;
cout<<A[low]<<endl;
}
else
QuickSort( A, low, high);
}
int main()
{
int kd;
cin>>kd;
cin.ignore();
if(kd==0){
vector<int> A;
createvector( A );
QuickSort( A );
}
else if(kd==1){
vector<double>A;
createvector( A );
QuickSort( A );
}
else if(kd==2){
vector<char>A;
createvector( A );
QuickSort( A );
}
else if(kd==3){
vector<string >A;
createvector( A );
QuickSort( A );
}
else
cout<<"err"<<endl;
return 0;
}