剑指Offer:面试题题17 合并两个排序的链表

/*
合并两个排序的链表:
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是按照递增排序的。例如输入图中的链表1和
链表2,则合并之后的升序链表入链表3所示


链表1: 1 3 5 7
链表2: 2 4 6 8
链表3: 1 2 3 4 5 6 7 8




输入:
输入可能包含多个测试样例,输入以EOF结束。
对于每个测试案例,输入的第一行为两个整数n和m(0<=n<=1000, 0<=m<=1000):n代表将要输入的第一个链表的元素的个数,m代表将要输入的第二个链表的元素的个数。
下面一行包括n个数t(1<=t<=1000000):代表链表一中的元素。接下来一行包含m个元素,s(1<=t<=1000000)。
输出:
对应每个测试案例,
若有结果,输出相应的链表。否则,输出NULL。
样例输入:
5 2
1 3 5 7 9
2 4
0 0
样例输出:
1 2 3 4 5 7 9
NULL
*/


/*
关键:
1 合并链表是一个递归过程。每次是选取两个链表头结点中的较小值称为当前节点,
if(pHead1->_iVal < pHead2->_iVal)//设置两个链表中的较小值为链表头结点
{
pMergeHead = pHead1;
pMergeHead->_next = mergeSortedList(pHead1->_next,pHead2);//经典啊,采用递归来解决指向的下一个节点问题
}
递归适用于能求解相同的子问题,并且对于最简单的子问题已经有解。
2 一旦碰到两个链表之一为空的情形,那么就应该返回另一个链表
if(!pHead1)//两个链表中一旦哪个链表为空,就返回剩余的链表,类似于归并排序,这是递归出口
{
return pHead2;
}
3 return pMergeHead;//返回归并后的头结点
*/
#include <stdio.h>
#include <string.h>
const int MAXSIZE = 1001;


typedef struct Node
{
int _iVal;
struct Node* _next;
}Node;


//实在不想删除节点,用静态数组
Node nodeArr1[MAXSIZE];
int _iIndex1;
Node nodeArr2[MAXSIZE];
int _iIndex2;


Node* createNode1()
{
return &nodeArr1[_iIndex1++];
}


Node* createNode2()
{
return &nodeArr2[_iIndex2++];
}


void buildList(Node** pHead,int* pArr,int n,Node* (*pFun)())
{
if(!pHead || !(*pHead))
{
return;
}
Node* pNode,*pCurNode;
for(int i = 0 ; i < n ; i++)
{
if(i)//尾插法建立单链表
{
pNode = pFun();//动态策略
pNode->_iVal = pArr[i];
pNode->_next = NULL;
pCurNode->_next = pNode;
pCurNode = pNode;
}
else
{
pCurNode = *pHead;
pCurNode->_iVal = pArr[i];
pCurNode->_next = NULL;
}
}
}








Node* mergeSortedList(Node* pHead1,Node* pHead2)//合并两个排序的单链表,这里为什么不用二级指针。这里也发生改变了啊?难道是为了书写方便?
{
if(!pHead1)//两个链表中一旦哪个链表为空,就返回剩余的链表,类似于归并排序,这是递归出口
{
return pHead2;
}
if(!pHead2)
{
return pHead1;
}
Node* pMergeHead = NULL;
if(pHead1->_iVal < pHead2->_iVal)//设置两个链表中的较小值为链表头结点
{
pMergeHead = pHead1;
pMergeHead->_next = mergeSortedList(pHead1->_next,pHead2);//经典啊,采用递归来解决指向的下一个节点问题
}
else
{
pMergeHead = pHead2;
pMergeHead->_next = mergeSortedList(pHead1,pHead2->_next);
}
return pMergeHead;//返回归并后的头结点
}


void printList(Node* pHead)
{
bool isFirst = true;
while(pHead)
{
if(!isFirst)
{
printf(" %d",pHead->_iVal);
}
else
{
isFirst = false;
printf("%d",pHead->_iVal);
}
pHead = pHead->_next;
}
printf("\n");
}


void freeList(Node** pHead)//释放链表,修改了链表,用二级指针
{
if(!pHead || !(*pHead))
{
return;
}
Node* pDelNode;
while(*pHead)//如果当前节点不空
{
pDelNode = *pHead;
*pHead = (*pHead)->_next;
delete pDelNode;
pDelNode = NULL;
}
}


void process()
{
int n,m;
while(EOF != scanf("%d %d",&n,&m))
{
if(!n && !m)
{
printf("NULL\n");
continue;
}
int iArr1[MAXSIZE];
int iArr2[MAXSIZE];
for(int i = 0 ; i < n ; i++)
{
scanf("%d",&iArr1[i]);
}
for(int j = 0 ; j < m ; j++)
{
scanf("%d",&iArr2[j]);
}
//初始化节点数组
memset(nodeArr1,NULL,sizeof(nodeArr1));
memset(nodeArr2,NULL,sizeof(nodeArr2));
_iIndex1 = 0;
_iIndex2 = 0;
Node* head1 =  createNode1();
Node** pHead1 = &head1;
Node* head2 = createNode2();
Node** pHead2 = &head2;
buildList(pHead1,iArr1,n,createNode1);
buildList(pHead2,iArr2,m,createNode2);
Node* pMergeHead = mergeSortedList(head1,head2);
printList(pMergeHead);//打印又不对链表进行改变,传一级指针即可
//freeList(&pMergeHead);//你说归并了之后,这个链表应该怎么删除?如果只删除当前的链表,会不会原来的两个链表内存泄露?
}
}


int main(int argc,char* argv[])
{
process();
getchar();
return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值