您的位置:首页 > 其它

将一个升序排列的单链表和一个降序排列的单链表合并成一个升序排列的单链表(优酷土豆2014校园招聘笔试题)

2013-10-16 20:16 357 查看
思路:首先可以将降序排列的单链表反转,这样两个链表均为升序,再将两个升序排列的单链表合并成一个升序排列的单链表。于是这里我们需要解决两个问题:

Q1:如何将一个单链表反转?

A1:以一般情况为例,下图(a)是一个单链表,图(b)是对图(a)已经实现若干结点反转的单链表,下一步我们需要对结点i进行反转,我们发现反转结点i之前,需要保存结点i所指的下一个结点j,否则在对结点i反转完成后,链表发生断裂,我们无法再寻找到结点j,也就无法进行后续的反转,同时在反转之前,我们还需要直到当前反转结点i的上一结点h,以让i结点指向h结点。因此,这里我们需要三个链表指针,分别保存当前要反转的结点(不妨设为pCurrentNode),当前要反转的结点的前一结点(不妨设为pPreNode),当前要反转的结点的后一结点(不妨设为pNextNode),对当前结点i反转完成后,我们将pPreNode设为当前结点i,将当前结点pCurrentNode指向要反转的下一结点j,pNextNode指向结点k,重复执行上述过程,直到当前结点pCurrentNode为空,即完成整个链表的反转。



Q2:如何将两个升序排列的单链表(设为pList1和pList2)合成一个升序排列的单链表(设为pMergeList)?

A2:对于两个升序排列的单链表pList1和pList2,我们可以先比较两个链表的头结点,将头结点值小的(假如是pList1)作为加入合并后的链表的末尾,然后将pList1的第二个结点作为头结点,同样对上述两个链表的头结点进行比较,重复上述同样的操作。对于多次重复的操作我们可以用递归完成。这里我们需要注意:如果两个要合并的链表其中一个为空(假设为pList1),则合并后的结果为另一个链表pList2,如果两个链表同时为空,则返回NULL。

最终实现代码如下:

#include <iostream>
using namespace std;

struct ListNode
{
int m_nValue;
ListNode *m_pNext;
};

ListNode * CreateList();
void ListTravesal(ListNode *pHeadList);
ListNode * ReverseNode(ListNode *pHeadList);
ListNode * Merge2OrderdeList(ListNode *pList1, ListNode *pList2);

int main()
{
ListNode *pList1 = NULL;
ListNode *pList2 = NULL;
ListNode *pMergeList = NULL;

cout<<"Please input the Ascend list1:"<<endl;
pList1 = CreateList();
cout<<"Please input the Decend list2:"<<endl;
pList2 = CreateList();
cout<<"The result of the List1 Travesal is:";
ListTravesal(pList1);
cout<<"The result of the List2 Travesal is:";
ListTravesal(pList2);

pList2 = ReverseNode(pList2);
cout<<"The result of the Reverse of List2 Travesal is:";
ListTravesal(pList2);

cout<<"The Merge of the two List is:"<<endl;
pMergeList = Merge2OrderdeList(pList1, pList2);
ListTravesal(pMergeList);

while(true);
return 0;
}
// 创建一个单链表
ListNode * CreateList()
{
ListNode *pHeadList = NULL;		//	链表头指针
ListNode *pPreNode = NULL;		//	当前创建结点的前一个结点
ListNode *pCurrentNode = NULL;	//	当前所创建的链表结点
int LenList = 0;				//	链表长度
int NodeValue = 0;				//	输入的链表结点值
int Index = 0;					//	索引

cout<<"Please input the Length of the List:"<<endl;
cin>>LenList;
for(Index=0; Index<LenList; Index++)
{
pCurrentNode = new ListNode;
cin>>NodeValue;
pCurrentNode->m_nValue = NodeValue;
pCurrentNode->m_pNext = NULL;
if(0 == Index)											//	如果是头结点
{
pPreNode = pCurrentNode;
pHeadList = pCurrentNode;
}
else
{
pPreNode->m_pNext = pCurrentNode;					//	连接当前创建的结点
}
pPreNode = pCurrentNode;								//	当前链表结点的末尾
}
return pHeadList;
}

//	遍历一个单链表
void ListTravesal(ListNode *pHeadList)
{
//cout<<"The result of the List Travesal is:";
while(NULL != pHeadList)
{
cout<<pHeadList->m_nValue<<" ";
pHeadList = pHeadList->m_pNext;
}
cout<<endl;
}

//反转一个单链表
ListNode * ReverseNode(ListNode *pHeadList)
{
ListNode *pReverseList = NULL;
ListNode *pCurrentNode = pHeadList;
ListNode *pPreNode = NULL;
ListNode *pNextNode = NULL;

if(NULL == pHeadList)
return NULL;
while(NULL != pCurrentNode)							//	反转结束条件:当前结点为空
{
pNextNode = pCurrentNode->m_pNext;				//	反转当前结点之前,保存下一结点
if(NULL == pNextNode)							//	如果当前结点的下一结点为空,说明当前结点为原链表的尾结点,反转后链表的头结点
{
pReverseList = pCurrentNode;
}
if(pHeadList == pCurrentNode)					//	特殊情况,当前结点时头结点
{
pCurrentNode->m_pNext = NULL;
}
else
{
pCurrentNode->m_pNext = pPreNode;			//	当前结点指向前一个结点
}
pPreNode = pCurrentNode;						//	将当前结点设为前一个结点为下一个结点的反转做准备
pCurrentNode = pNextNode;						//	设下一个节点为当前结点
}
return pReverseList;								//	返回反转后的链表的头结点
}

//	按升序合并两个单链表
ListNode * Merge2OrderdeList(ListNode *pList1, ListNode *pList2)
{
ListNode *pMergeList = NULL;

if(NULL == pList1)
{
return pList2;
}
if(NULL == pList2)
{
return pList1;
}

if(pList1->m_nValue < pList2->m_nValue)
{
pMergeList = pList1;
pMergeList->m_pNext = Merge2OrderdeList(pList1->m_pNext, pList2);
}
else
{
pMergeList = pList2;
pMergeList->m_pNext = Merge2OrderdeList(pList1, pList2->m_pNext);
}
return pMergeList;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: