归并排序算法

来源:互联网 发布:windows pe 硬盘版 编辑:程序博客网 时间:2024/06/06 10:04

这个算法感觉比插入难理解一些,下面说说我的理解:归并排序的步骤:

1.把长度为n的序列分为两个长度为n/2的子序列

2.对这两个子序列分别采用归并排序

3.将两个子序列合并成一个最终的排序序列

 

通过步骤2可看到 在归并排序中又用了归并排序,可见这是一个递归的过程。

例如一个数组 a[8] = {5, 2, 4, 7, 1, 3, 2 ,6} 下面采用递归排序

 

先进行第一步:把这个数组分成两个长度为4的数组{5, 2, 4, 7} ,{1, 3, 2, 6}

然后第二步:对两个数组分别再采用归并排序。这样的话就又回到了第一步,再次对刚得到的两个数组拆分得到{5, 2},{4, 7}和{1, 3},{2 ,6}这时得到了四个数组又是一次递归调用了再次拆分成{5},{2}和{4},{7}和{1},{3}和{2},{6}。可能大家也注意到了我这里的两个数组是一一对应的{5}对应 {2},这和数组值的位置有关。到了这一步 每一个数组里面就只有一个元素了就不可以再拆分了。

 

第三步:因为我们在第二步中最后把数组拆分成了每一个里面只有一个元素的n个数组了,所以在这一步我们要比较元素的大小 然后把n个数组再次组合成一个排好序的数组。因为第一步和第二步是循环执行的,也就是:第一步--》第二步--》第一步--》》第二步。。。所以在第三步开始时我们得到的是拆分成一个数组只有一个元素的n个数组了。

我们先两两比较{5},{2} 比组成新的数组{2, 5} ;{4}和{7}比组成新的数组{4, 7}..这样第一次组成完之后 我们得到了{2, 5}{4, 7}{1, 3}{2, 6}这些都是排好序的数组。

然后再执行第三步,把这四个数组再次比较再次组合:一样是两两比较,先比较2和4,2小于4 把2放在新的数组的最前面,然后再比较5和4,5大于4把4放在新数组的第二位,再比较5和7.。这样就又得到了两个新的数组{2, 4, 5, 7} {1, 2, 3, 6}

然后我们再次执行第三步 把两个新的排好序的数组组合成一个新的数组。这就是我们想要的结果了。(大家可能也注意到了第二步拆了多少下,第三步就要组合多少下。。这里我举的例子中数组元素为偶数个也就是每次拆分时数组元素个数都是一样的,如果数组元素为奇数个也是可以的 大家可以试着推算下)

下面是代码部分:

 

main(void)

{

sort(0, LEN-1); /*LEN为数组的长度*/

return 0;

}

 

void sort(int start, int end)

{

int mid;

if(start < end) {  /*这里判断一下不拆分的条件*/

mid = (start + mid) / 2;

sort(start, mid);   /*递归调用*/

sort(mid+1, end);

merge(start, mid, end); /*对数组排序,重组*/

}

}

 

void merge(int start, int mid, int end)

{

int n1 = mid - start + 1;

int n2 = end - mid;

int i, j, k;

int left[n1], right[n2]; /*数组left 和 right即为两两对应的数组*/

 

for(i = 0; i < n1; i++) {

left[i] = a[start+i];

}

for(j = 0; j < n2; j++) {

right[j] = a[mid+1+j];

}

 

i = j = 0;

k = start;

while(i < n1 && j < n2) {

if(left[i] < right[j])  /*若左边数组的元素小于右边数组的元素,则把左边数组的元素赋给新的数组,并拿到左边下一个元素*/

a[k++] = left[i++];

else

a[k++] = right[j++];

}

while(i < n1) { /*拆分成的两个数组中,left数组元素多于right数组时*/

a[k++] = left[i++];

}

while(j < n2) { /*拆分成的两个数组中,right数组元素多于left数组时*/

a[k++] = right[j++];

}

 

}

 

 

以上是我的个人理解,有不对的地方,请大家多多指教,谢谢!!!

 

原创粉丝点击