二路归并排序(链式存储)

来源:互联网 发布:游戏多核优化的多吗 编辑:程序博客网 时间:2024/05/22 14:19

设单链表结构为 struct ListNode {
int data ;
ListNode * link ;
};
下面的程序是以单链表为存储结构, 实现二路归并排序的算法, 要求链表不另外占用存储空间, 排序过程中不移动结点中的元素, 只改各链结点中的指针, 排序后r仍指示结果链表的第一个结点.在初始状态下, 所有待排序记录链接在一个以r为头指针的单链表中.例如,
在算法实现时,利用了一个队列做为辅助存储, 存储各有序链表构成的归并段的链头指针.初始时, 各初始归并段为只有一个结点的有序链表.队列的数据类型为Queue, 其可直接使用的相关操作有置空队列操作:makeEmpty ( );将指针x加入到队列的队尾操作:EnQueue ( ListNode * x );退出队头元素, 其值由函数返回的操作:ListNode *DlQueue ( );判队列空否的函数, 空则返回1, 不空则返回0:int IsEmpty( ). 
解决方法提示:
程序首先对待排序的单链表进行一次扫描, 将它划分为若干有序的子链表, 其表头 指针存放在一个指针队列中.当队列不空时, 从队列中退出两个有序子链表, 对它们进行二路归并, 结果链表的表头指针存放到队列中.
如果队列中退出一个有序子链表后变成空队列, 则算法结束.这个有序子链表即为所求.在算法实现时有 6 处语句缺失,请阅读程序后补上.
(提示:先对待排序的单链表进行一次扫描, 将它划分为若干有序的子链表, 其表头指针存放在一个指针队列中。当队列不空时重复执行, 从队列中退出两个有序子链表, 对它们进行二路归并, 结果链表的表头指针存放到队列中。如果队列中退出一个有序子链表后变成空队列, 则算法结束。这个有序子链表即为所求。)
(1) 两路归并算法

void merge ( ListNode * ha, ListNode * hb,, ListNode *& hc ) {ListNode *pa, *pb, *pc ; if ( ha→data <= hb→data ){ hc = ha; pa = ha→link; pb = hb;}else { hc = hb; pb = hb→link; pa = ha ; }pc = hc;while ( pa && pb ) if (pa→data <= pb→data) {pc→link = pa; pc = pa; pa = pa→link;}else{ pc→link = pb; pc = pb;pb = pb→link;}if ( pa ) pc→link = pa;else pc→link = pb;}

(2) 归并排序主程序

void mergesort ( ListNode * r ) {ListNode * s, t; Queue Q ;if ( ! r ) return; s = r; Q.EnQueue( r );while ( s ) { t = s→link;while ( t != 0 && s→data <= t→data ) { s = t; t = t→link; }if ( t ) { s→link = 0; s = t;Q.EnQueue( s );}}while ( !Q.IsEmpty( ) ) {r = Q.DlQueue( );if ( Q.IsEmpty( ) ) break;s = Q.DlQueue( );merge( r, s, t );Q.EnQueue( t );}}