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

来源:互联网 发布:win10蓝牙 软件 编辑:程序博客网 时间:2024/04/29 03:24

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

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

粗体为划分基准 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_MAXint 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_MAXint 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 6int 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