原文档地址:http://blog.csdn.net/lalor/article/details/7429989
问题定义:
写一个函数SortedMerge函数,该函数有两个参数,都是递增的链表,函数的功能就是合并这两个递增的链表为一个递增的链表,SortedMerge的返回值是新的链表。新链表由前两个链表按元素递增顺序合并而成,也就是说它不会创建新的元素。
比如:这里有两个链表,分别是
list1: 5->10->15
list2: 2->3->20
SortedMerge函数返回一个指向新链表的指针,新链表应该是如下这样的:2->3->5->10->15->20
程序需要考虑如下情况:两个链表(函数参数)都有可能为空,也可能其中一个链表已经遍历完了,另一个链表还有很多元素。
方法1(虚拟节点)
这种方法用一个虚拟节点(dummy node)作为结果链表的起始节点,为了方便在链表尾部插入节点,还需要用一个尾指针指向链表的尾节点。
初始时,结果链表为空的时候,尾指针指向的是虚拟节点。因为虚拟节点是一个在栈上分配的临时变量,所以对它的操作都是非常高效的。在循环迭代中,每次从a或b中取一个节点插入到结果链表的尾部,循环结束时,虚拟节点的next域就是结果链表的地址,也就是我们期望的返回值。
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
-
-
- struct node
- {
- int data;
- struct node* next;
- };
-
-
- void push(struct node** head_ref, int new_data)
- {
-
- struct node* new_node = (struct node*)malloc(sizeof(struct node));
-
-
- new_node->data = new_data;
-
-
- new_node->next = (*head_ref);
-
-
- (*head_ref) = new_node;
- }
-
-
- void printList(struct node* node)
- {
- while(node != NULL)
- {
- printf("%d ", node->data);
- node = node->next;
- }
- printf("\n");
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- void MoveNode(struct node** destRef, struct node** sourceRef)
- {
-
- struct node* newNode = *sourceRef;
- assert(newNode != NULL);
-
-
- *sourceRef = newNode->next;
-
-
- newNode->next = *destRef;
-
-
- *destRef = newNode;
- }
-
-
-
- struct node* SortedMerge(struct node* a, struct node* b)
- {
-
- struct node dummy;
-
-
- struct node* tail = &dummy;
-
-
- 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);
- }
-
- int main(int argc, char* argv[])
- {
-
-
- struct node* res = NULL;
- struct node* a = NULL;
- struct node* b = NULL;
-
-
-
-
- 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;
- }
方法2(局部引用)
这种方法与上一种方法非常相似。这种方法避免使用虚拟节点(dummy node),而是使用一个指向指针的指针,struct node** lastPtrRef,这个指针指向结果链表的最后一个节点。在这个方法中,所有由虚拟节点完成的工作都有lastPtrRef完成。
-
- struct node* SortedMerge(struct node* a, struct node* b)
- {
- struct node* result = NULL;
-
-
- struct node** lastPtrRef = &result;
-
- while(1)
- {
- if(a == NULL)
- {
- *lastPtrRef = b;
- break;
- }
- else if(b == NULL)
- {
- *lastPtrRef = a;
- break;
- }
- if(a->data <= b->data)
- {
- MoveNode(lastPtrRef, &a);
- }
- else
- {
- MoveNode(lastPtrRef, &b);
- }
-
- lastPtrRef = &((*lastPtrRef)->next);
- }
- return (result);
- }
方法3(递归)
合并操作是非常适合用递归来完成的一类操作,递归实现将会比迭代实现更加清晰且易于理解。尽管如此,你可能也不愿意使用递归来实现这个操作,因为递归方法所使用的栈空间与链表的长度成正比。
-
- struct node* SortedMerge(struct node* a, struct node* b)
- {
- struct node* result = NULL;
-
-
- if(a == NULL)
- return (b);
- else if(b == NULL)
- return (a);
-
-
- if(a->data <= b->data)
- {
- result = a;
- result->next = SortedMerge(a->next, b);
- }
- else
- {
- result = b;
- result->next = SortedMerge(a, b->next);
- }
- return (result);
- }
原文网址:
http://www.geeksforgeeks.org/archives/3622