快速排序

归并排序一样,快速排序也是基于分治法的。下面是对一个典型的子数组A[p..r]排序的分治过程的步骤:

1.分解:将数组数组A[p..r]划分成两个(可能为空)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每一个元素都小于A(q),且A[q+1..r]大于等于元素A(q)。总之,就是以A[q]为分界点进行划分,具体的步骤稍后说明。

2.解决:通过递归调用快速排序算法,对A[p..q-1]和A[q+1..r]进行排序。

3.合并:由于两个子数组就地排序(就是不需要额外的空间),所以合并不需要任何操作



一些具体的实现过程可以参考代码上的注释:

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

//测试的数组的最大数目为MAX
#define MAX 10

//分割的过程,这里是将A[r]也就是最后一个元素作为比较的值
//想象一下,有两个指针i和j,一开始i指向第一个元素之前,而j指向i元素下一个
//然后j开始向右扫描,只要j指向的元素是大于A[r]的,那么j继续前进,此时i和j之间的元素必然全部大于A[r]
//而一旦出现j指向的元素小于A[r],这时候只需要将i的值加1,然后A[i]与A[j]互换,那么i的值左边的元素必然全部小于A[r]
//全部扫描完成后,i就成为了分割点,这时候只需要将i+1的值返回就可以了
int Partition(int* A,int p,int r)
{
    int x=A[r];
    int i=p-1;
    int j,temp;
    for(j=p;j<r;j++)
    {
        if(A[j]<=x)
        {
            i++;
            temp=A[i];A[i]=A[j];A[j]=temp;
        }
    }
    temp=A[i+1];A[i+1]=A[r];A[r]=temp;
    return i+1;
}

//快排的主算法,得到分割点后递归调用自身就行了
void Quick_Sort(int* A,int p,int r)
{
    int q;
    if(p<r)
    {
        q=Partition(A,p,r);
        Quick_Sort(A,p,q-1);
        Quick_Sort(A,q+1,r);
    }
}

//主程序进行数据测试
int main()
{
    int A[MAX]={34,6,2,56,34,3,22,56,4,1};
    Quick_Sort(A,0,9);
    int count;
    for(count=0;count<MAX;count++)
        printf("%d ",A[count]);
    printf("\n");
    return 0;
}
当然了,使用这种方式得到的快排算法并不是最优的,当给定的数组一开始就是排好序的或是逆序排好的,那么算法的时间复杂度将和冒泡排序一样差,解决的方法就是使用随机化算法,这里由于每次选择比较的元素都是A[r],也就是最后一个元素,而随机化的方法就是是比较的元素不确定化,将A[r]通过rand()或者其他什么随机函数进行选取,那么,算法的时间复杂度将不会取决于输入的有序程度(这就是概率论的知识了,我就不做详细说明了~)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值