算法题:合并两个有序列表
说明:这篇文章是学习交流,转载请注明出处。欢迎转载!
题目:已知有两个有序的单链表,其头指针分别为head1和head2。实现将这两个链表合并的函数:
Node* ListMerge(Node *head1,Node *head2)
这个算法非常像我们排序算法中的归并排序。仅仅能说“非常像”,由于思想是一样的,可是这个与归并排序还是有差别的。差别例如以下:
1.归并排序是针对有序数组。而这里是有序链表;
2.归并排序排序的时间复杂度为o(nlogn),而这里的时间复杂度最坏情况下为O(m+n),最好的情况下为O(min{m,n})。
3.归并排序须要又一次申请空间,而这里无需再又一次申请空间。仅仅需改变链表结点的指针指向。
而这里算法的思想跟归并排序是一样的,都是对两个待归并的线性表分别设置1个指针,比較这两个当前指针的大小,将小的结点加入到合并后的线性表中,并向后移动当前指针。若两个线性表中。至少有一个表扫描完。走将相应的还有一个表之间总体加入到合并后的线性表中。在这里:链表和数组的差别在于,链表仅仅须要改变当前合并序列尾指针的位置。而数组则要将剩下的值依次拷贝到归并表的尾部。
算法的递归实现例如以下:
Node *ListMerge1(Node *head1,Node *head2)//採用递归的方法实现 { if(head1==NULL) return head2; if(head2==NULL) return head1; Node *head=NULL; if(head1->value < head2->value) { head=head1; head->next=ListMerge1(head1->next,head2); } else { head=head2; head->next=ListMerge1(head1,head2->next); } return head; }
算法的非递归实现例如以下:
Node *ListMerge(Node *head1,Node *head2) { if(!head1) return head2; if(!head2) return head1; Node *head=NULL;//合并后的头指针 Node *p1=head1;//p1用于扫描链表1 Node *p2=head2;//p2用于扫描链表2 if(head1->value<head2->value) { head=head1; p1=head1->next; } else { head=head2; p2=head2->next; } Node *p=head;//p永远指向最新合并的结点 while(p1 && p2)//假设循环停止。则p1或p2至少有一个为NULL { if(p1->value<p2->value) { p->next=p1; p1=p1->next; } else { p->next=p2; p2=p2->next; } p=p->next; } if(p1)//假设链1还没走完 { p->next=p1; } else if(p2)//假设链2还没走完 { p->next=p2; } return head; }
整个測试代码例如以下:
#include<iostream> using namespace std; struct Node { int value; Node* next; Node(int v):value(v){} }; /*创建一个链表,1->2->3->4->5->6->7*/ Node* CreateList1()//创建一个有序的单链表1 { Node *head; Node *n1=new Node(1); Node *n3=new Node(3); Node *n5=new Node(5); Node *n7=new Node(7); Node *n9=new Node(9); head=n1; n1->next=n3; n3->next=n5; n5->next=n7; n7->next=n9; n9->next=NULL; return head; } Node* CreateList2()//创建一个有序的单链表2 { Node *head; Node *n2=new Node(2); Node *n4=new Node(4); Node *n6=new Node(6); Node *n8=new Node(8); head=n2; n2->next=n4; n4->next=n6; n6->next=n8; n8->next=NULL; return head; } void FreeList(Node *head)//将链表空间释放 { if(head==NULL) { return ; } else { Node *temp=head->next; delete head; head=temp; FreeList(head); } } void VisitList(Node *head)//遍历链表中的元素,用递归的方法遍历 { if(head) { cout<<head->value<<"->"; VisitList(head->next); } else { cout<<"null"<<endl; } } Node *ListMerge(Node *head1,Node *head2) { if(!head1) return head2; if(!head2) return head1; Node *head=NULL;//合并后的头指针 Node *p1=head1;//p1用于扫描链表1 Node *p2=head2;//p2用于扫描链表2 if(head1->value<head2->value) { head=head1; p1=head1->next; } else { head=head2; p2=head2->next; } Node *p=head;//p永远指向最新合并的结点 while(p1 && p2)//假设循环停止。则p1或p2至少有一个为NULL { if(p1->value<p2->value) { p->next=p1; p1=p1->next; } else { p->next=p2; p2=p2->next; } p=p->next; } if(p1)//假设链1还没走完 { p->next=p1; } else if(p2)//假设链2还没走完 { p->next=p2; } return head; } Node *ListMerge1(Node *head1,Node *head2)//採用递归的方法实现 { if(head1==NULL) return head2; if(head2==NULL) return head1; Node *head=NULL; if(head1->value < head2->value) { head=head1; head->next=ListMerge1(head1->next,head2); } else { head=head2; head->next=ListMerge1(head1,head2->next); } return head; } int main() { Node *head1=CreateList1(); Node *head2=CreateList2(); cout<<"归并前"<<endl; cout<<"链表1:"; VisitList(head1); cout<<"链表2:"; VisitList(head2); cout<<"合并后的链表:"; //Node *head=ListMerge(head1,head2); Node *head=ListMerge1(head1,head2); VisitList(head); FreeList(head); return 0; }
測试结果例如以下:
參测试数据-------------《剑指offer》
版权声明:本文博主原创文章。博客,未经同意,不得转载。