当前位置:编程学习 > 网站相关 >>

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

9.8.1 归并排序介绍
        前面我们讲了堆排序,因为它用到了完全二叉树,充分利用了完全二叉树的深度是⌊log2n⌋+1的特性,所以效率比较高。不过堆结构的设计本身是比较复杂的,老实说,能想出这样的结构就挺不容易,有没有更直接简单的办法利用完全二叉树来排序呢?当然是有。
        先来举一个例子。你们知道高考一本、二本、专科分数线是如何划分出来的吗?
        简单地说,如果各高校本科专业在某省高三理科学生中计划招收1万名,那么将全省参加高考的理科学生分数倒排序,第1万名的总分数就是当年本科生的分数线(现实可能会比这复杂,这里简化之)。也就是说,即使你是你们班级第一、甚至年级第一名,如果你没有上分数线,则说明你的成绩排不到全省前1万名,你也就基本失去了当年上本科的机会了。
        换句话说,所谓的全省排名,其实也就是每个市、每个县、每个学校、每个班级的排名合并后再排名得到的。注意我这里用到了合并一词。
我们要比较两个学生的成绩高低是很容易的,比如甲比乙分数低,丙比丁分数低。那么我们也就可以很容易得到甲乙丙丁合并后的成绩排名,同样的,戊己庚辛的排名也容易得到,由于他们两组分别有序了,把他们八个学生成绩合并有序也是很容易做到的了,继续下去……最终完成全省学生的成绩排名,此时高考状元也就诞生了。
        为了更清晰地说清楚这里的思想,大家来看图9-8-1,我们将本是无序的数组序列{16,7,13,10,9,15,3,2,5,8,12,1,11,4,6,14},通过两两合并排序后,再合并,最终获得了一个有序的数组。注意仔细观察它的形状,你会发现,它像极了一棵倒置的完全二叉树,通常涉及到完全二叉树结构的排序算法,效率一般都不低的——这就是我们要讲的归并排序法。
 

\

 


9.8.2 归并排序算法
        “归并”一词的中文含义就是合并、并入的意思,而在数据结构中的定义是将两个或两个以上的有序表组合成一个新的有序表。
        归并排序(Merging Sort)就是利用归并的思想实现的排序方法。它的原理是假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到⌈n/2⌉(⌈x⌉表示不小于x的最小整数)个长度为2或1的有序子序列;再两两归并,……,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。 
        好了,有了对归并排序的初步认识后,我们来看代码。

/* 对顺序表L作归并排序 */
void MergeSort(SqList *L)

  MSort(L->r,L->r,1,L->length);
}

 

        一句代码,别奇怪,它只是调用了另一个函数而已。为了与前面的排序算法统一,我们用了同样的参数定义SqList *L,由于我们要讲解的归并排序实现需要用到递归调用 ,因此我们外封装了一个函数。假设现在要对数组{50,10,90,30,70,40,80,60,20}进行排序,L.length=9,我现来看看MSort的实现。

/* 将SR[s..t]归并排序为TR1[s..t] */
1 void MSort(int SR[],int TR1[],int s, int t)
2 {
3  int m;
4  int TR2[MAXSIZE+1];
5  if(s==t)
6   TR1[s]=SR[s];
7  else
8  {
9   m=(s+t)/2;   /* 将SR[s..t]平分为SR[s..m]和SR[m+1..t] */
10   MSort(SR,TR2,s,m); /* 递归地将SR[s..m]归并为有序的TR2[s..m] */
11   MSort(SR,TR2,m+1,t); /* 递归地将SR[m+1..t]归并为有序TR2[m+1..t] */
12   Merge(TR2,TR1,s,m,t); /* 将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t] */
13  }
14 }

 

1) MSort被调用时,SR与TR1都是{50,10,90,30,70,40,80,60,20},s=1,t=9,最终我们的目的就是要

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,