内部排序——交换类排序——快速排序

快速排序

在冒泡排序中,由于扫描过程中只对相邻的两个元素进行比较,因此在互换两个相邻元素时只能消除一个逆序,如果能通过两个(不相邻的)元素的交换,消除待排序记录中的多个逆序则会大大加快排序的速度。快速排序方法中的一次交换可以消除多个逆序。
算法思想:从待排序记录序列中选取一个记录(通常选取第一个记录)为枢轴,其关键字设为k1 然后将其余关键字小于k1的记录移到前面,而将关键字大于k1的记录移到后面,结果将待排序序列分成两个子表,最后将关键字为k1的记录插入到其分界线的位置,将这个过程称为一趟快速排序。通过一次划分后就以关键字为k1的记录为界将待排序序列分成两个子表,且前面子表中的关键字均不大于k1,而后面子表中的所有记录的关键字均小于k1。对分割后的子表继续按上述原则进行分割,直到子表的长度不超过1为止。此时待排序记录序列就变成了一个有序表。
算法步骤:假设待划分序列为r[left],r[left+1],...r[right],具体实现上述过程时,可以可以设两个指针i,j 他们的初值可以分别为left和right。首先将基准记录r[left]移至变量x中,使r[left] 即r[i]相当于空单元,然后反复进行如下两个扫描过程,直到i和j相遇。
  • j从右向左扫描,直到r[j].key<x.key,将r[j]移至空单元r[i],此时r[j]相当于空单元。
  • i从左向右进行扫描,直到r[i].key>x.key,将r[i]移至空单元r[j],此时r[i]相当于空单元。
当i和j相遇时,r[i](或r[j])相当于空单元,且r[i]左边所有记录的关键字均不大于基准记录的关键字,而r[i]右边所有记录的关键字均不小于基准记录的关键字。最后将基准记录移至r[i]中就完成了一次划分过程,对于r[i]左边的子表和右边的子表可以采用同样的方法进行进一步划分。

排序过程如下所示:



两种实现方式 代码如下
第一种方式
int  QKPass(int r[],int low ,int high);
void QKSort(int r[],int low,int high);
//完整的快速排序算法  (方式一)
void QKSort(int r[],int low,int high){
    int pos;
    if(low<high){
        pos=QKPass(r, low, high);
        QKSort(r, low, pos-1);
        QKSort(r, pos+1, high);
    }
}
//一趟快速排序算法
int   QKPass(int r[],int low ,int high){
    /*对记录数组r中的r[low]至r[high]部分进行一趟快速排序,并得到基准的位置,使得排序后得结果满足其之后(之前)的记录的关键字不小于(大于)基准记录*/
    int x;
    x=r[low]; //选择基准记录
    while(low<high){
        while(low<high&&r[high]>=x)//high从右到左找小于x的记录
            high--;
        if(low<high) {r[low]=r[high];   low++;} /*找到小于x的记录 则送入空单元 “r[ low]”*/
        while(low<high&&r[low]<x)
            low++;
        if(low<high)  {r[high]=r[low]; high--;}/*low从左到右找大于x的记录,则送入空单元r[high]*/
    }
    r[low]=x;
    return  low;
}

第二种方式 代码如下
void  QuickSort(int r[],int left,int right){ //方式二
    int key=r[left];
    int low=left;
    int high=right;
    if(low<high){
        while(low<high){
            while(r[high]>key&&low<high) high--;
            r[low]=r[high];
            while(r[low]<key&&low<high) low++;
            r[high]=r[low];
        }
        r[low]=key;
        QuickSort(r, left, low-1);
        QuickSort(r, low+1, right);
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值