常見的鏈表排序(Java版)

       上篇博客中講解了九大內部排序算法,部分算法還提供了代碼實現,可是那些代碼實現都是基於數組進行排序的,本篇博客就以鏈表排序實現幾種常見的排序算法,以饗讀者。算法

 

快速排序的鏈表實現數組

算法思想:對於一個鏈表,以head節點的值做爲key,而後遍歷以後的節點,能夠獲得一個小於key的鏈表和大於等於key的鏈表;由此遞歸能夠對兩個鏈表分別進行快速。這裏用到了快速排序的思想即通過一趟排序可以將小於key的元素放在一邊,將大於等於key的元素放在另外一邊。函數

代碼實現:ui

 1     //快速排序
 2     public static void quickSort(ListNode begin, ListNode end){
 3         if(begin == null || begin == end)
 4             return;
 5         
 6         ListNode index = paration(begin, end);
 7         quickSort(begin, index);
 8         quickSort(index.next, end);
 9     }
10     
11     /**
12      * 劃分函數,以頭結點值爲基準元素進行劃分
13      * @param begin
14      * @param end
15      * @return
16      */
17     public static ListNode paration(ListNode begin, ListNode end){
18         if(begin == null || begin == end)
19             return begin;
20         
21         int val = begin.val;  //基準元素
22         ListNode index = begin, cur = begin.next;
23         
24         while(cur != end){
25             if(cur.val < val){  //交換
26                 index = index.next;
27                 int tmp = cur.val;
28                 cur.val = index.val;
29                 index.val = tmp;
30             }
31             cur = cur.next;
32         }
33         
34         
35         begin.val = index.val;
36         index.val = val;
37         
38         return index;
39     }

歸併排序的鏈表實現spa

算法思想:單鏈表與數組相比只能順序訪問每一個元素,所以在使用二路歸併排序時關鍵在於找到鏈表的中間結點將鏈表一分爲二:能夠利用快慢指針同時遍歷單鏈表,當步長爲2的指針指向鏈表最後一個結點或者最後一個結點的下一個結點時,步長爲1的指針即指向鏈表的中間結點。而後是兩個有序單鏈表的合併問題。時間複雜度爲O(N*logN),空間複雜度爲O(1)。指針

代碼實現:code

 1     //歸併排序
 2     public static ListNode mergeSort(ListNode head){
 3         if(head == null || head.next == null)  //空鏈表或者只有單個結點
 4             return head;
 5         ListNode slow = head, fast = head.next;
 6         
 7         while(fast != null && fast.next != null){  //使用快慢指針尋找中間 結點
 8             slow = slow.next;
 9             
10             fast = fast.next;
11             if(fast.next != null)
12                 fast = fast.next;        
13         }
14         
15         ListNode ptr1 = slow.next;
16         slow.next = null;
17         
18         ListNode tmp1 = mergeSort(head);
19         ListNode tmp2 = mergeSort(ptr1);
20         return merge(tmp1, tmp2);
21     }
22     
23     
24     public static ListNode merge(ListNode start1,  ListNode start2){
25         ListNode header = new ListNode(-1);
26         ListNode pre = header;
27         
28         ListNode ptr1 = start1, ptr2 = start2;
29         while(ptr1 != null && ptr2 != null){
30             if(ptr1.val <= ptr2.val){
31                 pre.next = ptr1;
32                 pre = ptr1;
33                 ptr1 = ptr1.next;
34             }else{
35                 pre.next = ptr2;
36                 pre = ptr2;
37                 ptr2 = ptr2.next;
38             }
39         }
40         while(ptr1 != null){
41             pre.next = ptr1;
42             pre = ptr1;
43             ptr1 = ptr1.next;
44         }
45         
46         while(ptr2 != null){
47             pre.next = ptr2;
48             pre = ptr2;
49             ptr2 = ptr2.next;
50         }
51         
52         
53         return header.next;
54         
55     }

冒泡排序的鏈表實現blog

算法思想:依次比較相鄰的結點,若是是逆序的就交換兩個結點排序

代碼實現:遞歸

 1     //冒泡排序
 2     public static ListNode bubbleSort(ListNode head){
 3         if(head == null || head.next == null)  //鏈表爲空或者僅有單個結點
 4             return head;
 5         
 6         ListNode cur = null, tail = null;
 7         
 8         cur = head;
 9         
10         while(cur.next != tail){
11             while(cur.next != tail){
12                 if(cur.val > cur.next.val){
13                     int tmp = cur.val;
14                     cur.val = cur.next.val;
15                     cur.next.val = tmp;
16                 }
17                 cur = cur.next;
18             }
19             
20             tail = cur;  //下一次遍歷的尾結點是當前結點(仔細琢磨一下里面的道道)
21             cur = head;     //遍歷起始結點重置爲頭結點    
22         }
23         
24         return head;
25         
26         
27     }

先寫這幾種吧,想起來再更。。。

相關文章
相關標籤/搜索