Merge sort

来源:互联网 发布:java开发物流管理系统 编辑:程序博客网 时间:2024/05/20 04:15

Backdrop

听萌神说归并排序有两种,意识到自己当年没有好好学。于是就上维基百科补了下课。
https://en.wikipedia.org/wiki/Merge_sort

Main

虽然说是两种,但是都是归并排序。也就是说思路是不变的。总共分两步:

  1. Divide the unsorted list into n sublists, each containing 1 element (a list of 1 element is considered sorted).
  2. Repeatedly merge sublists to produce new sorted sublists until there is only 1 sublist remaining. This will be the sorted list.

Bottom-up implementation

C-like Pseudocode

/* array A[] has the items to sort; array B[] is a work array */void BottomUpMergeSort(A[], B[], n){  /* Each 1-element run in A is already "sorted". */  /* Make successively longer sorted runs of length 2, 4, 8, 16... until whole array is sorted. */  for (width = 1; width < n; width = 2 * width)    {      /* Array A is full of runs of length width. */      for (i = 0; i < n; i = i + 2 * width)        {          /* Merge two runs: A[i:i+width-1] and A[i+width:i+2*width-1] to B[] */          /* or copy A[i:n-1] to B[] ( if(i+width >= n) ) */          BottomUpMerge(A, i, min(i+width, n), min(i+2*width, n), B);        }      /* Now work array B is full of runs of length 2*width. */      /* Copy array B to array A for next iteration. */      /* A more efficient implementation would swap the roles of A and B */      CopyArray(B, A, n);      /* Now array A is full of runs of length 2*width. */    }}void BottomUpMerge(A[], iLeft, iRight, iEnd, B[]){  i0 = iLeft;  i1 = iRight;  j;  /* While there are elements in the left or right runs */  for (j = iLeft; j < iEnd; j++)    {      /* If left run head exists and is <= existing right run head */      if (i0 < iRight && (i1 >= iEnd || A[i0] <= A[i1]))        {          B[j] = A[i0];          i0 = i0 + 1;        }      else        {          B[j] = A[i1];          i1 = i1 + 1;        }    }}void CopyArray(B[], A[], n){    for(i = 0; i < n; i++)        A[i] = B[i];}

Something

这个格式居然是 GNU,感觉好怀念……
其实关键在 mergesort 的描述居然是跟平时学习的不一样的。如果是根据上述的描述,代码自然就是 Bottom-up 形式的。
那么……第二种当然就是……

Top-down implementation

C-like Pseudocode

/* array A[] has the items to sort; array B[] is a work array */TopDownMergeSort(A[], B[], n){    TopDownSplitMerge(A, 0, n, B);}// iBegin is inclusive; iEnd is exclusive (A[iEnd] is not in the set)TopDownSplitMerge(A[], iBegin, iEnd, B[]){    if(iEnd - iBegin < 2)                       // if run size == 1        return;                                 //   consider it sorted    // recursively split runs into two halves until run size == 1,    // then merge them and return back up the call chain    iMiddle = (iEnd + iBegin) / 2;              // iMiddle = mid point    TopDownSplitMerge(A, iBegin,  iMiddle, B);  // split / merge left  half    TopDownSplitMerge(A, iMiddle,    iEnd, B);  // split / merge right half    TopDownMerge(A, iBegin, iMiddle, iEnd, B);  // merge the two half runs    CopyArray(B, iBegin, iEnd, A);              // copy the merged runs back to A}//  left half is A[iBegin :iMiddle-1]// right half is A[iMiddle:iEnd-1   ]TopDownMerge(A[], iBegin, iMiddle, iEnd, B[]){    i0 = iBegin, i1 = iMiddle;    // While there are elements in the left or right runs    for (j = iBegin; j < iEnd; j++) {        // If left run head exists and is <= existing right run head.        if (i0 < iMiddle && (i1 >= iEnd || A[i0] <= A[i1])) {            B[j] = A[i0];            i0 = i0 + 1;        } else {            B[j] = A[i1];            i1 = i1 + 1;            }    } }CopyArray(B[], iBegin, iEnd, A[]){    for(k = iBegin; k < iEnd; k++)        A[k] = B[k];}

Top-down implementation using lists

Pseudocode for top down merge sort algorithm which recursively divides the input list into smaller sublists until the sublists are trivially sorted, and then merges the sublists while returning up the call chain.

function merge_sort(list m)    // Base case. A list of zero or one elements is sorted, by definition.    if length(m) <= 1        return m    // Recursive case. First, *divide* the list into equal-sized sublists.    var list left, right    var integer middle = length(m) / 2    for each x in m before middle         add x to left    for each x in m after or equal middle         add x to right    // Recursively sort both sublists    left = merge_sort(left)    right = merge_sort(right)    // Then merge the now-sorted sublists.    return merge(left, right)function merge(left, right)    var list result    while notempty(left) and notempty(right)        if first(left) <= first(right)            append first(left) to result            left = rest(left)        else            append first(right) to result            right = rest(right)    // either left or right may have elements left    while notempty(left)        append first(left) to result        left = rest(left)    while notempty(right)        append first(right) to result        right = rest(right)    return result

Natural merge sort

这个是 mergesort 的 Bottom-up 形式经过一点改动得到的。
Bottom-up 形式是一开始划分成 n 个 长度为 1 的子序列,然而 Natural merge sort 则充分利用了原来序列的连续递增的部分,把连续递增的部分划分为一个子序列。
下面给出一个例子:

Start       : 3--4--2--1--7--5--8--9--0--6Select runs : 3--4  2  1--7  5--8--9  0--6Merge       : 2--3--4  1--5--7--8--9  0--6Merge       : 1--2--3--4--5--7--8--9  0--6Merge       : 0--1--2--3--4--5--6--7--8--9

如果序列是单调递减的,那么 Natural merge sort 也就没有额外的优势。

0 0
原创粉丝点击