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

设单链表结构为 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 );
	}
}


  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值