题目:已知有两个有序的单链表,其头指针分别为head1和head2,实现将这两个链表合并的函数:
Node* ListMerge(Node *head1,Node *head2)
算法的递归实现如下:
<span style="font-size:14px;">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;
}</span>
算法的非递归实现如下:
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;
}
(虚拟节点)
这种方法用一个虚拟节点(dummy node)作为结果链表的起始节点,为了方便在链表尾部插入节点,还需要用一个尾指针指向链表的尾节点。
初始时,结果链表为空的时候,尾指针指向的是虚拟节点。因为虚拟节点是一个在栈上分配的临时变量,所以对它的操作都是非常高效的。在循环迭代中,每次从a或b中取一个节点插入到结果链表的尾部,循环结束时,虚拟节点的next域就是结果链表的地址,也就是我们期望的返回值。
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- /*Link list node*/
- struct node
- {
- int data;
- struct node* next;
- };
- /*Function to insert a node at the begining of the linked list*/
- void push(struct node** head_ref, int new_data)
- {
- /* allocate node*/
- struct node* new_node = (struct node*)malloc(sizeof(struct node));
- /* put in the data*/
- new_node->data = new_data;
- /*link the old list off the new node*/
- new_node->next = (*head_ref);
- /*move the head to point to the new node*/
- (*head_ref) = new_node;
- }
- /* Function to print nodes in a given linked list */
- void printList(struct node* node)
- {
- while(node != NULL)
- {
- printf("%d ", node->data);
- node = node->next;
- }
- printf("\n");
- }
- /*pull off the front node of the source and put it in dest*/
- /* MoveNode() function takes the node from the front of the source, and move it to
- the front of the dest.
- It is an error to call this with the source list empty.
- Before calling MoveNode():
- source == {1, 2, 3}
- dest == {1, 2, 3}
- After calling MoveNode():
- source == {2, 3}
- dest == {1, 1, 2, 3}
- */
- void MoveNode(struct node** destRef, struct node** sourceRef)
- {
- /* the front source node */
- struct node* newNode = *sourceRef;
- assert(newNode != NULL);
- /*Advance the source pointer */
- *sourceRef = newNode->next;
- /* Link th eold dest off the new node */
- newNode->next = *destRef;
- /*Move dest to point to the new node */
- *destRef = newNode;
- }
- /*Takes two lists sorted in creasing order, and splices their nodes together to
- make ont big sorted list which is returned. */
- struct node* SortedMerge(struct node* a, struct node* b)
- {
- /* a dummy first node to hang the result on */
- struct node dummy;
- /* tail points to the last result node */
- struct node* tail = &dummy;
- /*so tail->next is the places to add new nodes to the result*/
- dummy.next = NULL;
- while(1)
- {
- if(a == NULL)
- {
- tail->next = b;
- break;
- }
- else if(b == NULL)
- {
- tail->next = a;
- break;
- }
- if(a->data <= b->data)
- {
- MoveNode(&(tail->next), &a);
- }
- else
- {
- MoveNode(&(tail->next), &b);
- }
- tail = tail->next;
- }
- return (dummy.next);
- }
- /*Drier program to test above functions */
- int main(int argc, char* argv[])
- {
- /*start with the empty list */
- struct node* res = NULL;
- struct node* a = NULL;
- struct node* b = NULL;
- /*Let us create two sorted linked lists to test the functions
- Created lists shall be a:5->10->15, b:2->3->20 */
- push(&a, 15);
- push(&a, 10);
- push(&a, 5);
- push(&b, 20);
- push(&b, 3);
- push(&b, 2);
- res = SortedMerge(a, b);
- printf("\nMerged Linked List is:\n");
- printList(res);
- return 0;
- }
1996

被折叠的 条评论
为什么被折叠?



