内部排序(二)快速排序

快速排序(QuickSort)是对冒泡排序的一种改进,故在介绍快速排序之前,我们先介绍冒泡排序。

1、冒泡排序

原理:将第一个记录的关键字和第二个记录的关键字进行比较,若为逆序,则交换(假设正序输出),然后比较第二个记录和第三个记录的关键字。以此类推,直至第n-1个记录和第n个记录的关键字进行比较,这是第一趟。然后第二趟,第三趟……
过程演示

算法代码:(算法很简单,双重循环)

#include <stdio.h>
#include <stdlib.h>

void main(){
    int array[5] = { 5, 3, 1, 2, 8 };
    int temp=array[0];//临时变量
    int length=5;
    for (int i = 0; i < length-1; i++){//外循环控制趟数
        for (int j = 0; j < length-1-i; j++){//内循环控制比较
            if (array[j]>array[j+1]){
                temp = array[j];
                array[j] = array[j+1];
                array[j + 1] = temp;
            }

        }

    }

    for (int k = 0; k < length; k++){
        printf("%d", array[k]);
    }

    system("pause");
}

2、快速排序

原理:快排是对冒泡排序的一种改进。基本思想是通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,已达到整个序列有序。
算法叙述:一趟排序的具体做法是:附设两个指针low和high,它们的初值分别是low和high,设枢轴记录的关键字为pivotkey,则首先从high所指位置向前搜索找到第一个关键字小于pivotkey的记录,和枢轴记录交换之(即逆序交换,假设我们要从小到大输出),然后从low所指位置起向后搜索,找到第一个关键字大于pivotkey的记录,和枢轴相互交换(逆序交换)重复这两部,直至low=high为止。
此时记录被枢轴分成两部分,左边的都比枢轴小,右边的都比枢轴大。
然后进行第二趟,将枢轴左边的全部记录再当成一个记录序列,再次使用刚刚的方法。
算法演示
(i就是low,j就是high)
这里写图片描述
算法代码


#define MAXSIZE 20
typedef int KeyType;//定义关键字类型为int
typedef char InfoType;//定义其他信息类型为char

typedef struct{//定义记录类型
    KeyType key;
    InfoType otherinfo;
}RedType;
typedef struct{//定义顺序表类型
    RedType r[MAXSIZE + 1];//r[0]闲置或作为哨兵
    int length;//顺序表的长度
}SqList;

//在实现我们刚刚的算法时,每交换一次,需进行三次移动。
//但实际上对枢轴记录的移动是多余的,
//因为只有在一趟排序结束时,即low=high的位置才是枢轴记录的最后位置。
//故我们将枢轴暂存到r[0],一趟结束后再移到正确位置。

//此函数进行一趟排序。返回枢轴的位置。(此过程的演示只需把上图每一次交换的枢轴量用空白代替就行)
int partition(SqList *L, int low, int high){
    int pivotkey;
    L->r[0] = L->r[low];//用子表的第一个记录作为枢轴记录。
    pivotkey = L->r[low].key;//用pivotpoint标识

    while (low < high){

        while (low<high&&L->r[high].key>=pivotkey){//从后向前找到要(向前)移动的关键字的下标
            high--;
        }
        L->r[low] = L->r[high];//把找的的点(向前)移动

        while (low < high&&L->r[low].key <= pivotkey){//从前往后找到要(向后)移动的关键字的下标
            low++;
        }
        L->r[high] = L->r[low];//把找到的点(向后)移动

    }
    L->r[low] = L->r[0];//枢轴量放到该放置的位置

    return  low;//返回枢轴量的下标
}

void QSort(SqList *L, int low, int high){
    //对顺序表中子序列L->r[low...high]作快速排序
    int pivotloc;

    if (low<high){//如果长度大于1
        pivotloc = partition(L, low, high);//进行一趟排序,将L->r[low...high]分为两个子序列,本趟枢轴下标赋给pivotloc
        QSort(L, low, pivotloc - 1);//对低子表进行递归排序
        QSort(L, pivotloc + 1, high);//对高子表进行递归排序
    }

}

void QuickSort(SqList *L){
    QSort(L,1,L.length);
}

评价
点:快速排序的平均时间为T(n)=knInn,其中n为待排序列中记录的个数,k为某个时间常数,经验证明,在所有同数量级的此类排序方法中,快速排序的常数因子k最小。因此,就平均时间而言,快速排序是目前被认为最好的一种内部排序方法。
点:若初始记录序列按关键字有序或基本有序时,快速排序将退化为冒泡排序,时间复杂度为O(n^2).改进的方法是依“三者取中”的法则来选枢轴记录。(此处不详细介绍)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值