您的位置:首页 > 其它

【算法】分治法之归并排序实现

2016-11-03 12:17 302 查看
所谓分治:分而治之,中华民族智慧的结晶。对其联盟,使其分裂而利于各个击破;对其国使用,使其国分裂而利于控制;对其公司使用,使其公司分裂而利于控制;对其团队使用,使其团队分裂而利于控制。可见,分治法被运用于当今社会的方方面面。

既然分治法拥有那么大能量,有必要学习学习它。当然了,这里学习分治是用来如何解决问题的。

面对一个大问题,如果直接去解决,可能很复杂,不好解决。所以要把大的问题分解成小问题,先解决小问题,等小问题都解决了,再一梳理,可能就把大问题也解决了。

所以分治法的基本步骤就是:

1. 认清问题,问题是否能够使用分治法

2.分解问题,把问题分解成小规模的一系列子问题

3.求解问题,把小规模问题一一求解

4.合并

分治法的典型使用: 二分查找、归并排序

各种情况下时间复杂度都能达到O(nlgn),理论上O(nlgn)已经是最优性能了。

递归算法公式或者说主方法:

T(n)=aT(n/b)+f(n);

a 代表问题规模

b 代表每个问题是原来的1/b;

归并排序公式:

T(n)=2T(n/2)+f(n);

问题规模是2个,每次都是分半

那么根据算法主定理可以得到其时间复杂度是O(nlgn)

主定理请看:http://blog.chinaunix.net/uid-25267728-id-3802135.html

归并排序空间复杂度:

需要O(n)临时保存数据。

归并排序C 语言代码示例:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <error.h>
#include <errno.h>
#include <sys/socket.h>
#include <stdlib.h>

void merge(int data[],int start,int middle, int end);

void mergeSort(int data[],int start, int end){
if(data == NULL){
printf("data == NULL");
return;
}
if(start < end){
int middle = 0;
middle = (end + start)/2;
mergeSort(data,start, middle);
mergeSort(data,middle+1, end);
merge(data,start,middle,end);
}

}

void merge(int data[],int start,int middle, int end){
int i = 0;
int j = 0;
int k = 0;
int part1Size = middle -start+1;
int part2Size = end - middle;
int* data1 = (int*)malloc(sizeof(int)*part1Size);
int* data2 = (int*)malloc(sizeof(int)*part2Size);
if(data1 == NULL || data2 == NULL){
printf("data1 or data2 is null\n ");
return;
}
printf("\n");
printf("merge start \n ");
printf("merge data1 \n ");
for(i=0; i < part1Size; i++){
data1[i]= data[start+i];
printf(" %d",data1[i]);
}
printf("\n ");
printf("merge data2 \n ");
for(j=0; j < part2Size; j++){
data2[j]= data[middle+1+j];
printf(" %d",data2[j]);
}
printf("\n ");
i = 0;
j = 0;
for( k = start; k <= end && i< part1Size && j<part2Size; k++){
if(data1[i] < data2[j]){
data[k]=data1[i];
i++;
}else{
data[k]=data2[j];
j++;
}

}
//再拷贝余下的
for(i; i< part1Size; i++){
data[k++]=data1[i];
}
for(j; j< part2Size; j++){
data[k++]=data2[j];
}
//end
free(data1);
free(data2);
printf("merge end \n ");
}

int main(){
int i;
int data[]={3,4,1,2,9,8,6,32,15,16,11,7};
int len = sizeof(data)/sizeof(int);
mergeSort(data,0,len -1);

printf("\n");
printf(" get sort result\n");
for(i =0; i < len;i++){
printf(" %d",data[i]);
}
printf("\n");
return 0;
}

从以下执行过程 log可以看出,最终分解为两两比较,然后合并,之后比较个数逐步体增再合并。

merge start 

 merge data1 

  3

 merge data2 

  4

 merge end 

 

merge start 

 merge data1 

  3 4

 merge data2 

  1

 merge end 

 

merge start 

 merge data1 

  2

 merge data2 

  9

 merge end 

 

merge start 

 merge data1 

  2 9

 merge data2 

  8

 merge end 

 

merge start 

 merge data1 

  1 3 4

 merge data2 

  2 8 9

 merge end 

 

merge start 

 merge data1 

  6

 merge data2 

  32

 merge end 

 

merge start 

 merge data1 

  6 32

 merge data2 

  15

 merge end 

 

merge start 

 merge data1 

  16

 merge data2 

  11

 merge end 

 

merge start 

 merge data1 

  11 16

 merge data2 

  7

 merge end 

 

merge start 

 merge data1 

  6 15 32

 merge data2 

  7 11 16

 merge end 

 

merge start 

 merge data1 

  1 2 3 4 8 9

 merge data2 

  6 7 11 15 16 32

 merge end 

 

 get sort result

 1 2 3 4 6 7 8 9 11 15 16 32
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: