JAVA实现单链表快速排序


原文:https://blog.csdn.net/u011606714/article/details/66976034


请去查看原文,链接在上面


链表与数组排序的不同在于,数组里通过下标交换的开销是O(1)的,而链表是O(n)的。所以,直接照搬数组的快速排序到链表,速度会很慢。

但是链表有一个优点,就是把元素移动到尾部,时间是O(1)的。

思路如下:

将链表的第一个元素设置为pivot,遍历之后的n-1个元素,如果该元素的值大于pivot,则将其放在链表末尾(O(1)时间)。遍历所需时间是O(n)的。遍历之后,数组分为三个部分:【pivot】【比pivot小的元素】【比pivot大的元素】,将pivot插入后两部分中间,得到:【比pivot小的元素】【pivot】【比pivot大的元素】,此时,就可以对前后两部分进行递归了。算法复杂度为O(nlog(n))。

注意:quick_sort的三个参数分别为:start_pre,指向第一个元素的Node(即start_pre.next=start),len是链表的长度,end是尾指针(注意,end.next不一定为null)



[java]  view plain  copy
  1. import java.util.ArrayList;  
  2. import java.util.Collections;  
  3. import java.util.List;  
  4.   
  5.   
  6. public class LinkListSort {  
  7.     public static int [] random_order_array(int len){    
  8.         List <Integer> list = new ArrayList<Integer>();    
  9.         for (int i = 0; i < len; i ++){    
  10.             list.add(i);    
  11.         }    
  12.         Collections.shuffle(list);    
  13.         int [] array = new int [len];    
  14.         for (int i = 0; i < len; i ++)    
  15.             array[i] = list.get(i);    
  16.         return array;    
  17.     }    
  18.       
  19.     public static void print_mynode(MyNode node, int len){  
  20.         MyNode temp = node;  
  21.         for (int i = 0; i < len; i ++){  
  22.             System.out.print(temp.val + " ");  
  23.             temp = temp.next;  
  24.         }  
  25.         System.out.println();  
  26.     }  
  27.       
  28.     
    public static void quiksort(MyNode start_pre, int len, MyNode end){
        if (len <= 1)
            return;
        MyNode start = start_pre.next;
        int pivot_val = start.val;
        int split_position = 0;
    
        MyNode temp0 = start;
        MyNode temp1 = start.next;
        for (int i = 1; i < len; i ++){
            if (temp1.val > pivot_val){ //放到链表末尾
                if (temp1 != end){//temp1为当前的节点,如果相等,表示已经全部比较过了
                    temp0.next = temp1.next;//放到链表末尾第1步:temp0 为前一个节点,这里是将temp1的下一个节点,放到temp0的next,便于移动temp1
                    temp1.next = end.next;//放到链表末尾第2步:把end.next放到temp1的next,便于下一步将temp1放到最后
                    end.next = temp1;//放到链表末尾第3步:把temp1放到最后
                    end = temp1;//此时temp1成为了最后一个,以后再有需要放到最后的节点,就要放到新的最后节点的next,即temp1.next
                    temp1 = temp0.next;//开始下一轮比较
                }
            }
            else{
                //不需要移动的情况
                temp1 = temp1.next;//开始准备下一轮比较
                temp0 = temp0.next;//开始准备下一轮比较,为相等做准备
    
                split_position ++;//表示比当前节点小的节点数量
            }
        }
        MyNode pivot_node = start;
        /*
        如果相等,表示没有比start大的数据,如果不想等,表示存在比start大的数据;
        temp0是比start小的数据中,最大的那个;
        所以pivot_node 要放在temp0和temp1之间
         */
        if (temp0 != start){
            start_pre.next = pivot_node.next;
            temp0.next = pivot_node;
            pivot_node.next = temp1;
        }
        quiksort(start_pre, split_position, temp0);
        quiksort(pivot_node, len - split_position - 1, end);
    }
  29.       
  30.     public static void main(String [] args){  
  31.           
  32.         int len = 20;  
  33.         int [] array = random_order_array(len);  
  34.         //int [] array = {0, 3, 2, 8, 6, 9, 7, 5, 1, 4 };  
  35.         //int [] array = {3, 2, 8, 6, 9, 7, 5, 1, 4  };  
  36.         MyNode start = new MyNode(array[0]);  
  37.         MyNode temp = start;  
  38.         for (int i = 1; i < array.length; i ++){  
  39.             temp.next = new MyNode(array[i]);  
  40.             temp = temp.next;  
  41.         }  
  42.         MyNode end = start;  
  43.         for (int i = 0; i < len - 1; i ++){  
  44.             end = end.next;  
  45.         }  
  46.         MyNode start_pre = new MyNode(-1);  
  47.         start_pre.next = start;  
  48.         System.out.println("乱序数组:");  
  49.         print_mynode(start_pre.next, len);  
  50.         quiksort(start_pre, len, end);  
  51.         System.out.println("排序后数组:");  
  52.         print_mynode(start_pre.next, len);  
  53.     }  
  54. }  
  55.   
  56. class MyNode{  
  57.     int val;  
  58.     MyNode next = null;  
  59.     public MyNode(int val){  
  60.         this.val = val;  
  61.     }  
  62. }  


输出结果举例:

[plain]  view plain  copy
  1. 乱序数组:  
  2. 19 16 1 6 2 17 11 3 8 5 9 0 18 15 4 7 14 13 10 12   
  3. 排序后数组:  
  4. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19   

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值