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

来源:互联网 发布:ubuntu 命令行解压zip 编辑:程序博客网 时间:2024/05/16 13:54
/*合并两个排序的链表:输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是按照递增排序的。例如输入图中的链表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 21 3 5 7 92 40 0样例输出:1 2 3 4 5 7 9NULL*//*关键: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;}


 

0 0
原创粉丝点击