算法题——单链表的归并排序

题目:单链表的归并排序,返回排序后的链表。传统的归并都是数组,可以随机访问元素,链表则需要顺序遍历找中间结点。

 

思路

设置两个指针,一个步长为1, 一个步长为2,当快指针到达尾结点时,慢指针指向中间结点,时间复杂度为O(N);

平分为左链表L1和右链表L2,递归分裂,直到链表为空或者只有一个结点;

将链表L2的每个结点插入到链表L1中,时间复杂度为O(m+n),m、n分别为两条链表的长度。

 

画出递归树,可知总的时间复杂度为O(N * lgN)。

 

代码

合并两个有序的链表:

 1 struct ListNode
 2 {
 3     int value;
 4     ListNode *next;
 5     ListNode(int v): value(v), next(NULL)
 6     {
 7     }
 8 };
 9 
10 ListNode *mergeSortedList(ListNode *L1, ListNode *L2)
11 {
12     ListNode dummy(-1), *p1 = &dummy, *p2 = L2;  //L1的辅助头结点dummy,因为可能在头部插入
13     dummy.next = L1;
14     while(p1->next != NULL && p2 != NULL)  //停止条件,也包括了判断两个链表是否为空
15     {
16         if(p1->next->value >= p2->value)
17         {
18             L2 = p2->next;
19             p2->next = p1->next;
20             p1->next = p2;
21             p1 = p2;
22             p2 = L2;
23         }
24         else
25         {
26             p1 = p1->next;
27         }
28     }
29     if(p1->next == NULL)    //L2可能还有未处理的结点,直接加在L1尾部即可
30     {
31         p1->next = p2;
32     }
33 
34     return dummy.next;
35 }

 

单链表的归并排序:

 1 ListNode *listMergeSort(ListNode *head)
 2 {
 3     if(head == NULL || head->next == NULL)   //链表为空,或者只有一个结点,直接返回
 4         return head;
 5     
 6     ListNode *slow = head, *fast = head;
 7     while(fast->next != NULL && fast->next->next != NULL)
 8     {
 9         fast = fast->next->next;
10         slow = slow->next;
11     }
12 
13     ListNode *leftHead = head, *rightHead = slow->next;
14     slow->next = NULL;      //需要把左半链表的尾结点的next赋空值,所以用一个变量来记录右半链表的头
15 
16     leftHead  = listMergeSort(leftHead);
17     rightHead = listMergeSort(rightHead);
18 
19     return mergeSortedList(leftHead, rightHead);
20 }

 

posted @ 2014-08-17 03:23  阿杰的专栏  阅读(9493)  评论(1编辑  收藏  举报