对链表进行归并排序

MergeSort for List

Last time I started with the simplest question of reversing a linked list this time let me go a bit further – sorting a linked list.

Just for a minute consider sorting a linked list , some of the standard sorting mechanism assumes random access of data (like quick sort, heapsort ) so linked list becomes a special case. But then we have one more wonderful sort left to consider , which is merge sort. Merge sort is very special (in fact many standard sort libraries like in java internally uses a combination of merge sort and insertion sort) because it has the wonderful property of being a stable sort. In fact it is the only stable sort with asymptotic complexity of O(nlogn) but its draw back typically is the use of O(n) extra space. There are wonderful inline merge sort algorithms which I would cover in a different post altogether. Now what is more wonderful is that for sorting linked list, we can use merge sort’s O(nlogn) without the drawback of O(n) space. Again a quick search in net seem to suggest it is a very complicated algorithm to implement , again I am not sure why , this is my version of it (in Java).

The basic idea of merge sort is this basic recursive idea , how most of us learned recursion to start with -

merge_sort(list) {
  split list into two halfs, say first and second ;
  merge_sort(firstHalf);
  merge_sort(secondHalf);
  merge(firstHalf,secondHalf);
}

A working implementation in Java :

    public Node merge_sort(Node head) {
        if(head == null || head.next == null) { return head; }
        Node middle = getMiddle(head);      //get the middle of the list
        Node sHalf = middle.next; middle.next = null;   //split the list into two halfs

        return merge(merge_sort(head),merge_sort(sHalf));  /recurse on that
    }

    public Node merge(Node a, Node b) {
        Node dummyHead, curr; dummyHead = new Node(); curr = dummyHead;
        while(a !=null && b!= null) {
            if(a.info <= b.info) { curr.next = a; a = a.next; }
            else { curr.next = b; b = b.next; }
            curr = curr.next;
        }
        curr.next = (a == null) ? b : a;
        return dummyHead.next;
    }

    public Node getMiddle(Node head) {
        if(head == null) { return head; }
        Node slow, fast; slow = fast = head;
        while(fast.next != null && fast.next.next != null) {
            slow = slow.next; fast = fast.next.next;
        }
        return slow;
    }

原文地址:
http://www.dontforgettothink.com/2011/11/23/merge-sort-of-linked-list/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
链表归并排序中的实现和数组不同,我们需要使用快慢指针来找到链表的中间节点。下面是使用 C 语言实现链表归并排序的示例代码: ```c #include <stdio.h> #include <stdlib.h> // 定义链表节点结构体 struct ListNode { int val; struct ListNode* next; }; // 分割链表 struct ListNode* splitList(struct ListNode* head) { struct ListNode* slow = head; struct ListNode* fast = head; while (fast->next && fast->next->next) { slow = slow->next; fast = fast->next->next; } struct ListNode* temp = slow->next; slow->next = NULL; return temp; } // 合并两个有序链表 struct ListNode* merge(struct ListNode* l1, struct ListNode* l2) { if (!l1) return l2; if (!l2) return l1; if (l1->val < l2->val) { l1->next = merge(l1->next, l2); return l1; } else { l2->next = merge(l1, l2->next); return l2; } } // 归并排序 struct ListNode* mergeSort(struct ListNode* head) { if (!head || !head->next) { return head; } struct ListNode* mid = splitList(head); struct ListNode* left = mergeSort(head); struct ListNode* right = mergeSort(mid); return merge(left, right); } // 打印链表 void printList(struct ListNode* head) { while (head) { printf("%d ", head->val); head = head->next; } } int main() { // 创建链表 struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode)); head->val = 3; head->next = (struct ListNode*)malloc(sizeof(struct ListNode)); head->next->val = 2; head->next->next = (struct ListNode*)malloc(sizeof(struct ListNode)); head->next->next->val = 4; head->next->next->next = (struct ListNode*)malloc(sizeof(struct ListNode)); head->next->next->next->val = 1; head->next->next->next->next = NULL; // 排序链表 head = mergeSort(head); // 打印链表 printList(head); return 0; } ``` 在这个示例代码中,我们首先定义了一个链表节点结构体 `ListNode`,然后定义了 `splitList()` 函数用于分割链表,`merge()` 函数用于合并两个有序链表,`mergeSort()` 函数用于实现链表归并排序。最后,我们创建了一个链表,对其进行排序,并使用 `printList()` 函数打印排序后的链表元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值