【问题标题】:Linked List Merge Sort Exaplanation链表合并排序说明
【发布时间】:2012-02-23 03:26:47
【问题描述】:

谁能给我解释一下,这段代码是如何工作的:

http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.c

我不明白这篇文章中使用的算法。谢谢

【问题讨论】:

    标签: algorithm sorting linked-list mergesort


    【解决方案1】:

    归并排序通常是对链表进行排序的首选。链表的缓慢随机访问性能使得其他一些算法(如快速排序)表现不佳,而其他算法(如堆排序)则完全不可能。

    设head为要排序的链表的第一个节点,headRef为head的指针。请注意,我们需要在 MergeSort() 中引用 head,因为下面的实现会更改下一个链接以对链表(不是节点处的数据)进行排序,因此如果原始 head 处的数据不是最小值,则必须更改头节点在链表中。

    合并排序(headRef)

    1) 如果 head 为 NULL 或链表中只有一个元素 然后返回。

    2) 否则将链表分成两半。 FrontBackSplit(head, &a, &b); /* a 和 b 是两半 */

    3) 对 a 和 b 两半进行排序。 合并排序(一); 合并排序(b);

    4) 合并排序后的 a 和 b(使用这里讨论的 SortedMerge()) 并使用 headRef 更新头指针。 *headRef = SortedMerge(a, b);

    /* Link list node */ struct node { int data; struct node* next; }; /* function prototypes */ struct node* SortedMerge(struct node* a, struct node* b); void FrontBackSplit(struct node* source, struct node** frontRef, struct node** backRef); /* sorts the linked list by changing next pointers (not data) */ void MergeSort(struct node** headRef) { struct node* head = *headRef; struct node* a; struct node* b; /* Base case -- length 0 or 1 */ if ((head == NULL) || (head->next == NULL)) { return; } /* Split head into 'a' and 'b' sublists */ FrontBackSplit(head, &a, &b); /* Recursively sort the sublists */ MergeSort(&a); MergeSort(&b); /* answer = merge the two sorted lists together */ *headRef = SortedMerge(a, b); } /* See http://geeksforgeeks.org/?p=3622 for details of this function */ 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 data) { result = a; result->next = SortedMerge(a->next, b); } else { result = b; result->next = SortedMerge(a, b->next); } return(result); } /* UTILITY FUNCTIONS */ /* Split the nodes of the given list into front and back halves, and return the two lists using the reference parameters. If the length is odd, the extra node should go in the front list. Uses the fast/slow pointer strategy. */ void FrontBackSplit(struct node* source, struct node** frontRef, struct node** backRef) { struct node* fast; struct node* slow; if (source==NULL || source->next==NULL) { /* length next; /* Advance 'fast' two nodes, and advance 'slow' one node */ while (fast != NULL) { fast = fast->next; if (fast != NULL) { slow = slow->next; fast = fast->next; } } /* 'slow' is before the midpoint in the list, so split it in two at that point. */ *frontRef = source; *backRef = slow->next; slow->next = NULL; } } /* Function to print nodes in a given linked list */ void printList(struct node *node) { while(node!=NULL) { printf("%d ", node->data); node = node->next; } } /* Function to insert a node at the beginging 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; } /* Drier program to test above functions*/ int main() { /* Start with the empty list */ struct node* res = NULL; struct node* a = NULL; struct node* b = NULL; /* Let us create a unsorted linked lists to test the functions Created lists shall be a: 2->3->20->5->10->15 */ push(&a, 15); push(&a, 10); push(&a, 5); push(&a, 20); push(&a, 3); push(&a, 2); /* Remove duplicates from linked list */ MergeSort(&a); printf("\n Sorted Linked List is: \n"); printList(a); getchar(); return 0; }

    【讨论】:

      【解决方案2】:

      尝试对数组的正常合并排序中执行的所有合并进行成像:首先,元素配对并合并到长度为 2 的排序子数组中,然后将这些长度为 2 的子数组配对并合并到长度四等。注意子数组的长度:1、2、4 等等,我们称之为instep,它在每次迭代中翻倍。

      在任何时候,p 指向长度为 instep 的列表,q 指向长度为 instep 或更小的列表(我们可能会到达列表的末尾),q 立即关注p。它们形成如上所述的一对子阵列。我们对pq 进行合并,以获得从p 开始的长度为psize + qsize 的排序列表。然后我们将pq 移动到下一对,依此类推。完成整个列表后,我们将 instep 加倍并开始合并更长的排序列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-24
        • 1970-01-01
        • 2020-09-25
        • 2010-09-05
        • 1970-01-01
        相关资源
        最近更新 更多