数据结构——归并排序

来源:互联网 发布:php web 应用开发 编辑:程序博客网 时间:2024/05/18 00:38

由于准备复习考研,趁闲暇时练练算法,偶然看到一篇归并排序的文章,提起了兴趣,于是捣腾一番,查阅了一些资料以及几位大神的博客,做以下记录。


参考资料:


白话经典算法系列之五 归并排序的实现

http://blog.csdn.net/morewindows/article/details/6678165

《大话数据结构》第9章 排序 9.8 归并排序(上)

http://www.cnblogs.com/cj723/archive/2011/04/25/2026751.html

《大话数据结构》第9章 排序 9.8 归并排序(下)

http://www.cnblogs.com/cj723/archive/2011/04/26/2026886.html



1、算法思想:

[数据结构]中要合并两个有序线性表时,每次取出头部较小的一个加入合并的表后面,再读其下一个,最后剩下的那个线性表中的所有元素全部加速合并表后面。


2、利用这种思想对数据排序

:利用递归的思想,将一个数组、链表一直均等分割下去,直到每个组只剩下一个为止;

:将之前分割后的数组两两之间合并,结果再两两合并....一直合并下去,直到只剩下一个数组。



3、源代码之递归实现

#include <stdio.h>#include "list_sort.h"//merge a segment of an array, minimum at the firstvoid merge1( int *arr, int first, int mid, int last, char *temp ){int i = first;int j = mid + 1;int k = 0;while ( i <= mid && j <= last ){if ( arr[i] < arr[j])temp[k++] = arr[i++];elsetemp[k++] = arr[j++];}while ( i <= mid )temp[k++] = arr[i++];while ( j <= last )temp[k++] = arr[j++];for ( k = first; k <= last; k++ )arr[k] = temp[k - first];}//use temp to save memoryvoid mergeSort1( int *arr, int first, int last, char *temp ){if ( first < last ){int mid = (first + last) / 2;mergeSort1 ( arr, first, mid, temp );mergeSort1 ( arr, mid + 1, last, temp );merge1 ( arr, first, mid, last, temp );}}void merge_Array_Sort1(int *arr, int len){char temp[len + 1];mergeSort1(arr, 0, len - 1, temp);}


4、递归实现的时间复杂度和空间复杂度分析

整个归并排序需要将数组拆分log2N次,即调用了log2N次递归函数。

每次递归都对N个数据进行了操作。所以,时间复杂度为:O(N*logN)

由于栈有log2N层,每一层总共要维护N个数据,所以空间复杂度也是:O(N*logN)


这样看来,其时间复杂度、空间复杂度并不高。

递归算法易于读懂、实现起来较为容易,但是其空间复杂度仍可进一步下降。所以我再用非递归的方法实现了归并排序。



5、非递归的归并排序


#include <stdio.h>#include <stdlib.h>#include "list_sort.h"void merge2( int *arr1, int *arr2, int first, int mid, int last ){int i = first;int j = mid + 1;int k = first;while ( i <= mid && j <= last ){if ( arr1[i] < arr1[j])arr2[k++] = arr1[i++];elsearr2[k++] = arr1[j++];}while ( i <= mid )arr2[k++] = arr1[i++];while ( j <= last )arr2[k++] = arr1[j++];}//将arr1(长度为len),每段间隔为s,两两合并到arr2void mergeSort2( int *arr1, int *arr2, int len, int s ){int i = 0;int j = 0;int first;int mid;int last;//所有长度为s的分段两两合并int times = len / (2 * s);for ( i = 0; i < times; i++ ){first = 2 * i * s;mid = first + s - 1;last = first + 2 * s - 1;merge2( arr1, arr2, first, mid, last);}//倒数第二段长度为s,最后一段长度大于0、小于sint remain = len % (s * 2);first = 2 * times * s;if ( remain > s ){mid = first + s - 1;last = len - 1;merge2( arr1, arr2, first, mid, last );}elsefor( j = first; j < len; j++ )arr2[j] = arr1[j];}void merge_Array_Sort2( int *arr, int len ){int i;int *temp = (int *)malloc(sizeof(int) * len);int s = 1;while (s < len){mergeSort2 ( arr, temp, len, s );s *= 2;for (i = 0; i < len; i++){arr[i] = temp[i];}}}


易得其空间复杂度为N。









0 0
原创粉丝点击