归并排序算法研究

最近阅读啦归并排序相关资料,结合自己的理解整理并编程实现进行测试验证。

归并排序利用啦分而治之的思想,将复杂问题转变为简单问题而后进行处理,然后对处理的结果在进行处理,最后得到需要的结果。

归并排序算法的为代码描述如下:

已知array[start..middle-1] and array[middle..end]都已经排好序啦

Merge(array, start, middle, end):

   Create left[..] = array[start..middle-1];

                right[..] = array[middle..end];

   i = j =0;

   for k <– start up to end

      if  (left[i] <=right[j] and i < middle – start )or j > end – middle

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

      else

         array[k] = left[j++]; 

MergeSort(array, start, end):

   if start < end

      middle = (start + end)/2;

      MergeSort(array, start, middle);

      MergeSort(array, middle+1, end);

      Merge(array, start, middle+1, end);

上述描述为增序排序,降序排序只需要将left[i] <=right[j]改变为left[i] >=right[j]即可。

将上述伪代码用C语言实现,增减type参数以便实现增序排序和将需排序。为了便于清晰了解递归,对于每一步都进行啦打印,显示每次归并的结果。代码如下:

#include <stdio.h>
typedef enum
{
  NON_DECREASE,
  NON_INCREASE
}t_sort;

void output_arry(int *array, int n)
{
  int i;
  for(i = 0; i < n; i++)
  {
    printf ("%d ", array[i]);
  }
  printf ("\n");
}

int recursive = 1;
void merge(int *array, int start, int middle, int end, t_sort type)
{
  int i,j,k;
  int *left = (int*)malloc(sizeof(int) * (middle - start));
  int *right = (int*)malloc(sizeof(int) * (end - middle + 1));  
  for(i = 0; i < middle - start; i++)
   left[i] = array[start + i];
  printf ("Left array: "); 
  output_arry(left, middle - start);
  for(i = 0; i < end - middle + 1; i++)
   right[i] = array[middle + i];
  printf ("Right array: "); 
  output_arry(right, end - middle + 1);
  for(k = start, i = 0, j = 0; k <= end; k++)
  {
    if(type == NON_DECREASE)
    {
      if((left[i] <= right[j] && i < middle - start) || j > end - middle)
      {
        array[k] = left[i++];
        printf ("L: %d\n", array[k]); 
      }
      else
      {
        array[k] = right[j++];
        printf ("R: %d\n", array[k]);     
      }
    }
    else
    {
      if((left[i] >= right[j] && i < middle - start) || j > end - middle)
      {
        array[k] = left[i++];
        printf ("L: %d\n", array[k]); 
      }
      else
      {
        array[k] = right[j++];
        printf ("R: %d\n", array[k]);     
      }
    }
  }
  printf ("--%d Merged array: ", recursive); 
  output_arry(array + start, end - start + 1);
  free(left);
  free(right);
}
void merge_sort(int *array, int start, int end, t_sort type)
{
  int middle;
  if(start < end)
  {
    middle = (start + end)/2;
    merge_sort(array, start, middle, type);
    merge_sort(array, middle+1, end , type);
    merge(array, start, middle+1, end, type);
    recursive ++;
  }
}

int
main(void)
{ 
  int arry[] = {10,7,8,4,5,2,1,6,3,8};   
  printf ("The original data is: ");
  output_arry(arry, sizeof(arry)/sizeof(int));
  merge_sort(arry, 0, sizeof(arry)/sizeof(int) - 1, NON_DECREASE);
  //merge_sort(arry, 0, sizeof(arry)/sizeof(int) - 1, NON_INCREASE);
  printf ("The sorted data is: ");
  output_arry(arry, sizeof(arry)/sizeof(int));
  return 0;
}

测试增序排序结果如下:

The original data is: 10 7 8 4 5 2 1 6 3 8 
Left array: 10 
Right array: 7 
R: 7
L: 10
--1 Merged array: 7 10 
Left array: 7 10 
Right array: 8 
L: 7
R: 8
L: 10
--2 Merged array: 7 8 10 
Left array: 4 
Right array: 5 
L: 4
R: 5
--3 Merged array: 4 5 
Left array: 7 8 10 
Right array: 4 5 
R: 4
R: 5
L: 7
L: 8
L: 10
--4 Merged array: 4 5 7 8 10 
Left array: 2 
Right array: 1 
R: 1
L: 2
--5 Merged array: 1 2 
Left array: 1 2 
Right array: 6 
L: 1
L: 2
R: 6
--6 Merged array: 1 2 6 
Left array: 3 
Right array: 8 
L: 3
R: 8
--7 Merged array: 3 8 
Left array: 1 2 6 
Right array: 3 8 
L: 1
L: 2
R: 3
L: 6
R: 8
--8 Merged array: 1 2 3 6 8 
Left array: 4 5 7 8 10 
Right array: 1 2 3 6 8 
R: 1
R: 2
R: 3
L: 4
L: 5
R: 6
L: 7
L: 8
R: 8
L: 10
--9 Merged array: 1 2 3 4 5 6 7 8 8 10 
The sorted data is: 1 2 3 4 5 6 7 8 8 10 

测试降序排序结果如下:

The original data is: 10 7 8 4 5 2 1 6 3 8 
Left array: 10 
Right array: 7 
L: 10
R: 7
--1 Merged array: 10 7 
Left array: 10 7 
Right array: 8 
L: 10
R: 8
L: 7
--2 Merged array: 10 8 7 
Left array: 4 
Right array: 5 
R: 5
L: 4
--3 Merged array: 5 4 
Left array: 10 8 7 
Right array: 5 4 
L: 10
L: 8
L: 7
R: 5
R: 4
--4 Merged array: 10 8 7 5 4 
Left array: 2 
Right array: 1 
L: 2
R: 1
--5 Merged array: 2 1 
Left array: 2 1 
Right array: 6 
R: 6
L: 2
L: 1
--6 Merged array: 6 2 1 
Left array: 3 
Right array: 8 
R: 8
L: 3
--7 Merged array: 8 3 
Left array: 6 2 1 
Right array: 8 3 
R: 8
L: 6
R: 3
L: 2
L: 1
--8 Merged array: 8 6 3 2 1 
Left array: 10 8 7 5 4 
Right array: 8 6 3 2 1 
L: 10
L: 8
R: 8
L: 7
R: 6
L: 5
L: 4
R: 3
R: 2
R: 1
--9 Merged array: 10 8 8 7 6 5 4 3 2 1 
The sorted data is: 10 8 8 7 6 5 4 3 2 1 

归并排序的时间复杂度为O(nlgn),从上面的测试结果可以看出相同的数在排序前后,其相对位置没有改变,因此它是一种稳定的排序。

 

点赞