排序-快速排序

快速排序是对冒泡排序的一种改进。

基本思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

输入:顺序表的长度,顺序表中各个元素。

输出:排好序的顺序表中各个元素。

运行结果:

冒泡排序通过一趟比较定位一个元素的最终位置。通过一趟比较能够获得更多的好处呢?

任取一个元素(如第一个)为枢轴,通过一趟比较,所有比枢轴小的元素一律前放,比枢轴大的元素一律后放。形成左右两个字表,对各字表重新选择中心元素并依次规则调整,直到每个子表的元素只剩一个。

辅助宏:

#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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值