版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liouyi250/article/details/78884826
周末闲着无聊,又把算法导论的书翻出来看了一下,终于经过一天时间把困扰我许久的分治排序算法做出来了。
分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。(百度百科)
假设有一个数组。未排序前是这样的,若想进行分治排序,1.是将数组分割,从图上可以看出,对于n个元素的数组,可以将其分割为log2(n)个不可分割小组。
2在分割好的数组(只含有两个元素或一个元素)排序,这里采用的是升序排序。将两个元素的位置交换即可。
3.合并数组,将图上两个元素的数组合并成一个数组。由于两个数组已经是升序排列好的,只用一次遍历这两个元素即可。
下面是详细的步骤图:
附上源码:
include <stdio.h>
include <stdlib.h>
void swap(int& a,int& b ){
int t=a;
a=b;
b=t;
}
void combine(int *a,int start,int split,int end){
if(split-start==1 && end-split==1) return;
int *b=(int*)malloc(sizeof(int)*(end-start));
int i=0,j=0;
int k=0;
for(;(i+j)!=(end-start);k++){
if(i!=split-start && j!=end-split){
if(a[start+i]>=a[split+j]){
b[k]=a[split+j];
j++;
continue;//continue是保证每次k都能自增
}
if(a[start+i]<a[split+j]){
b[k]=a[start+i];
i++;
continue;
}
}else{
if(i==split-start){
b[k]=a[split+j];
j++;
continue;
}else{
b[k]=a[start+i];
i++;
}
}
}
for(i=0;i<end-start;i++){
a[start+i]=b[i];
}
free(b);
b=NULL;
}
void mergesort(int *a,int start,int split,int end){
if(split-start==1 && end-split==1){
if(a[start]>a[split]){
swap(a[start],a[split]);
return;
}
}
if((split-start)*(end-split)==0) return;
int start1,split1,end1;
if(split-start>1){
split1=start+(split-start)/2;
end1=split;
mergesort(a,start,split1,end1);
combine(a,start,split1,end1);
}
if(end-split>1){
start1=split;
split1=start1+(end-split)/2;
mergesort(a,start1,split1,end);
combine(a,start1,split1,end);
}
combine(a,start,split,end);//这步很必须,不然排序无法完成
}
int main(){
int a[]={3,2,4,1,6,9,8,7,5,44,
32,54,23,56,876,54,23,45,34,67,
34,233,54,98,5,32,43,23,12,90,
78,65,43,32,21,56,43,32,56,43,
45,43,23,13,23,43,56,344,34,23};
mergesort(a,0,25,50);
for(int i=0;i<50;i++)
printf("%d ",a[i]);
}
程序效果图