算法小结--快速排序+归并排序

快速排序和归并排序都是采用分治的思想,将一个无序序列不断细分,然后慢慢组合成有序序列。

快速排序:它的基本思想是:根据基准通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

粗体为划分基准 key=4
序号 1 2 3 4 5 6 7 8
输入 4 2 8 7 1 3 5 6
从头部开始找比key大的数,找到后停留i=3,再从尾部开始找比key小的数j=6,找到后交换两个值,以此方式,知道i>=j 退出。
一次划分:2 3 1 4 7 8 5 6
然后 将 2 3 1 和 7 8 5 6 按第一次的方式划分
直至完成。

代码实现:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define n 5
//#define RAND_MAX
int a[n]={2,6,4,3,1};

void Swap(int i,int j)
{
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}


int Partition(int p,int r)
{
    int i = p,j=r+1;
    int x = a[p];
    while(1)
    {
        while(a[++i]<x&&i<r);  //从左到右,直到找到比x大的,或者i<r
        while(a[--j]>x);       //从右到左,直到找到比x小的
        if(i>=j) break;
        Swap(i,j);
    }
    a[p] = a[j]; //将基准插入对应位置
    a[j] = x;
    return j;
}

/*
int RandomPartition(int p,int r)
{
    int t =(int) (n*rand()/RAND_MAX); //产生0到n的整数
    Swap(t,p);
    return Partition(p,r);

}
*/

void QuickSort(int p,int r)
{
    int q;
    if(p<r)
    {
        q = Partition(p,r);
        //q = RandomPartition(p,r); //启用基准元素随机化
        QuickSort(p,q-1);
        QuickSort(q+1,r);
    }
}

int main()
{
    int i;
    QuickSort(0,n-1);
    for(i=0;i<n;i++)
    {
        printf("%d ",a[i]);
    }
    return 0;
}

快速排序一般情况都是以第一个元素作为key进行划分,这样容易出现太大的偶然性。如果key值差不多是这个有序序列的中间值,那么排序效率比较高,如果不能将序列划分成等同的两块,那么效率会降低。

改进方法,在序列中随机抽取key值,降低偶然性。
实现如下:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define n 5
//#define RAND_MAX
int a[n]={2,6,4,3,1};

void Swap(int i,int j)
{
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}


int Partition(int p,int r)
{
    int i = p,j=r+1;
    int x = a[p];
    while(1)
    {
        while(a[++i]<x&&i<r);  //从左到右,直到找到比x大的,或者i<r
        while(a[--j]>x);       //从右到左,直到找到比x小的
        if(i>=j) break;
        Swap(i,j);
    }
    a[p] = a[j]; //将基准插入对应位置
    a[j] = x;
    return j;
}


int RandomPartition(int p,int r)
{
    int t =(int) (p+(r-p)*rand()/RAND_MAX); //产生p到r的整数
    Swap(t,p);
    return Partition(p,r);

}


void QuickSort(int p,int r)
{
    int q;
    if(p<r)
    {
        //q = Partition(p,r);
        q = RandomPartition(p,r); //启用基准元素随机化
        QuickSort(p,q-1);
        QuickSort(q+1,r);
    }
}

int main()
{
    int i;
    QuickSort(0,n-1);
    for(i=0;i<n;i++)
    {
        printf("%d ",a[i]);
    }
    return 0;
}

归并排序:

合并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

这里写图片描述

代码如下:

#include <stdio.h>
#include <stdlib.h>
#define n 6
int a[n]={7,2,9,4,7,1};
int b[n]={0};

void Copy(int l,int r)
{
    int i;
    for(i=l;i<=r;i++)
    {
        a[i]=b[i];
    }
}

void Merge(int l,int m,int r)
{
    //合并c[l,m]和c[m+1,r] 到d[l,r]
    int i =l,j = m+1,k = l;
    while( (i<=m) && (j<=r))
    {
        if( a[i]<=a[j] ) b[k++]=a[i++];
        else b[k++] = a[j++];
    }

    int q;
    if(i>m)
    {
        for(q=j;q<=r;q++)
        b[k++]=a[q];

    }else
    {
        for(q=i;q<=m;q++)
        b[k++]=a[q];
    }


    int s;
    for(s=l;s<=r;s++)
    {
        //printf("%d \n",b[s]);
        a[s]=b[s];
    }
}

void MergeSort(int left,int right)
{
    if(left < right)
    {
        int i = (left+right)/2;
        MergeSort(left,i);
        MergeSort(i+1,right);
        Merge(left,i,right); //合并到数组b
        //Copy(left,right); //复制到数组a
    }
}

int main()
{
    MergeSort(0,n-1);
    int i;
    for(i=0;i<n;i++)
    {
        printf("%d ",a[i]);
    }
    printf("\n");
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值