自顶向下归并排序的应用——链表的随机化

     在对一个链表进行随机化时,可以借鉴自顶向下归并排序的思路,先将链表划分为左右两个子链表,分别进行随机化,然后再归并两个子链表,并在归并过程中进行随机化,代码如下:

// *pHead指向链表的首节点(不是头结点)
void RandomizeLinkedList(Link * pHead)
{
	int length = CountNodes(* pHead);
	Randomize(pHead,length);

	Link tail = * pHead;
	
    for(int i = 1;i < length;i++)
	{
		tail = tail->next;
	}
	
    tail->next = NULL;
}

// 随机化首节点由*pHead指向,长度为length的链表,随机化完成后*pHead指向链表新的首节点。该函数类似于自顶向下的归并排序
Randomize(Link * pHead,int length)
{
	if(length == 1)
	{
		return;
	}

	int lengthOfLeftSublist = length / 2;
    int lengthOfRightSublist = length - lengthOfLeftSublist;
	
	Link headOfRightSublist =  * pHead;
	for(int i = 0;i < countOfLeftSublist;i++)
	{
		headOfRightSublist = headOfRightSublist->next;
	}

	Randomize(pHead,lengthOfLeftSublist);
	Randomize(&headOfRightSublist,lengthOfRightSublist);

	Merge(pHead,length,lengthOfLeftSublist,headOfRightSublist);
}

// 链表的首结点由*pHead指向,长度为length,对其已经完成随机化的左右子链表进行归并,归并完成后*pHead指向链表新的首节点
void Merge(Link * pHead,int length,int lengthOfLeftSublist,Link headOfRightSublist)
{
	Link headOfLeftSublist = * pHead;

	if(GetProbability((double)lengthOfLeftSublist/length)))
	{
		headOfLeftSublist = headOfLeftSublist->next;
		lengthOfLeftSublist--;
	}
	else
	{
		* pHead = headOfRightSublist;
		headOfRightSublist = headOfRightSublist->next;
	}

	length--;

	Link tail = * pHead;
	
	while(lengthOfLeftSublist > 0)
	{
		if(GetProbability((double)lengthOfLeftSublist/length)))
		{
			tail->next = headOfLeftSublist;
			headOfLeftSublist = headOfLeftSublist->next;
			lengthOfLeftSublist--;
		}
		else
		{
			tail->next = headOfRightSublist;
			headOfRightSublist = headOfRightSublist->next;
		}

		length--;
		tail = tail->next;
	}

	if(length > 0)
	{
	    tail->next = headOfRightSublist;
	}
}

bool GetProbability(double probability)
{
	return  rand() / RAND_MAX < probability;
}

  

 

posted @ 2013-12-15 11:01  姚来飞  阅读(259)  评论(0编辑  收藏  举报