快速排序是对冒泡排序的一种改进。
基本思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
输入:顺序表的长度,顺序表中各个元素。
输出:排好序的顺序表中各个元素。
运行结果:
冒泡排序通过一趟比较定位一个元素的最终位置。通过一趟比较能够获得更多的好处呢?
任取一个元素(如第一个)为枢轴,通过一趟比较,所有比枢轴小的元素一律前放,比枢轴大的元素一律后放。形成左右两个字表,对各字表重新选择中心元素并依次规则调整,直到每个子表的元素只剩一个。
辅助宏:
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
#define NULL 0
typedef char *InfoType;
typedef int KeyType; //设关键字为整型
顺序表的存储结构定义:
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
#define NULL 0
typedef char *InfoType;
typedef int KeyType; //设关键字为整型
复制元素r2到r1
void RedCopy(RedType &r1,RedType r2)
{
//复制元素r2到r1
r1.key=r2.key;
r1.otherinfo=r2.otherinfo;
}
算法实现:
划分:用最左侧元素作枢轴,存入哨所。设low和high指向两端。
high向左移动,一旦遇到小于枢轴的元素,则将其移动到左侧。放入low指向的位置。
low向右移动,一旦遇到大于枢轴的元素,则将其移动到右侧。放入high指向的位置。
high和low从两侧交替向中间移动,直到low=high,左侧均小于等于枢轴,右侧均大于等于枢轴。将枢轴记录填入重叠位置则完成划分。
int Partition(SqList &L,int low,int high)
{
/*划分
用最左侧元素作枢轴 存入哨所 设low和high指向两端
high向左移动 一旦遇到小于枢轴的元素,将其移到左
侧 放入low所指向的位置 low向右移动 一旦遇到大于
枢轴的元素 则将其移动到右侧 放入high所指向的位
置 high和low从两侧交替向中间移动 直至low=high,
左侧均小于枢轴,右侧均大于枢轴,将枢轴记录填入
重叠位置则完成划分*/
RedCopy(L.r[0],L.r[low]);
while(low<high)
{
while(low<high&&L.r[high].key>=L.r[0].key)
high--;
RedCopy(L.r[low],L.r[high]);
while(low<high&&L.r[low].key<L.r[0].key)
low++;
RedCopy(L.r[high],L.r[low]);
}
RedCopy(L.r[low],L.r[0]);
return low;
}
快速排序.
void QSort(SqList &L,int low,int high)
{
//快速排序
int pivotLoc;
if(low<high)
{
pivotLoc=Partition(L,low,high); //获取枢轴
QSort(L,low,pivotLoc-1); //递归
QSort(L,pivotLoc+1,high);
}
}
算法分析:
平均时间复杂度:O(N*logN) 平均最快
最坏时间复杂度:O(N^2)
平均空间复杂度:O(logN)
最坏空间复杂度O(N)
该算法是一种不稳定的算法。
改进:枢轴在两侧和中间择一。
找出low,mid,high中中间大小的值,并返回。
int Mid(SqList &L,int low,int mid,int high)
{
//找出low,mid,high中中间大小的值,并返回
if((L.r[low].key>=L.r[mid].key&&L.r[low].key<=L.r[high].key)||
(L.r[low].key>=L.r[high].key&&L.r[low].key<=L.r[mid].key))
return low;
if((L.r[mid].key>=L.r[low].key&&L.r[mid].key<=L.r[high].key)||
(L.r[mid].key>=L.r[high].key&&L.r[mid].key<=L.r[low].key))
return mid;
if((L.r[high].key>=L.r[mid].key&&L.r[high].key<=L.r[low].key)||
(L.r[high].key>=L.r[low].key&&L.r[high].key<=L.r[mid].key))
return high;
}
改进的划分:
int Partition(SqList &L,int low,int high)
{
/*划分
用最左侧元素作枢轴 存入哨所 设low和high指向两端
high向左移动 一旦遇到小于枢轴的元素,将其移到左
侧 放入low所指向的位置 low向右移动 一旦遇到大于
枢轴的元素 则将其移动到右侧 放入high所指向的位
置 high和low从两侧交替向中间移动 直至low=high,
左侧均小于枢轴,右侧均大于枢轴,将枢轴记录填入
重叠位置则完成划分*/
int mid=Mid(L,low,(low+high)/2,high); //改进
RedCopy(L.r[0],L.r[mid]); //取中间值为枢轴
RedCopy(L.r[mid],L.r[low]);
RedCopy(L.r[low],L.r[0]); //将枢轴与low位置位置互换
while(low<high)
{
while(low<high&&L.r[high].key>=L.r[0].key)
high--;
RedCopy(L.r[low],L.r[high]);
while(low<high&&L.r[low].key<L.r[0].key)
low++;
RedCopy(L.r[high],L.r[low]);
}
RedCopy(L.r[low],L.r[0]);
return low;
}