將兩個有序鏈表合并成一個有序鏈表

來源:互聯網
上載者:User

問題定義:

        寫一個函數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>/*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;}


方法2(局部引用)

        這種方法與上一種方法非常相似。這種方法避免使用虛擬節點(dummy node),而是使用一個指向指標的指標,struct node** lastPtrRef,這個指標指向結果鏈表的最後一個節點。在這個方法中,所有由虛擬節點完成的工作都有lastPtrRef完成。

/* method2 Using local References */struct node* SortedMerge(struct node* a, struct node* b){struct node* result = NULL;/*point to the last result pointer */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);}/*tricky:advance to point to the next ".next" field */lastPtrRef = &((*lastPtrRef)->next);}return (result);}

方法3(遞迴)

        合併作業是非常適合用遞迴來完成的一類操作,遞迴實現將會比迭代實現更加清晰且易於理解。儘管如此,你可能也不願意使用遞迴來實現這個操作,因為遞迴方法所使用的棧空間與鏈表的長度成正比。

/*Using Recursion*/struct node* SortedMerge(struct node* a, struct node* b){struct node* result = NULL;/*Base cases*/if(a == NULL)return (b);else if(b == NULL)return (a);/*Pick either a or b, and recur */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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.