快速排序和归并排序都是采用分治的思想,将一个无序序列不断细分,然后慢慢组合成有序序列。
快速排序:它的基本思想是:根据基准通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
粗体为划分基准 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;
}