【数据结构与算法】单链表排序

以前一直没有考虑过对单链表的排序,直到遇到Leetcode
一、快速排序
单链表的快速排序需要用到快速排序的单向扫描法,总体思路是用一快一慢两个指针,快指针用来寻找小于key的结点,慢指针用来指向当前找到的较小结点应该存储的位置。

    public static int partition(int[] nums,int start,int end){
        int fast=start+1;
        int slow=start;
        int key=nums[start];
        while(fast<=end){
            if(nums[fast]<key){
                slow++;
                Swap.swap(nums,slow,fast);
            }
            fast++;
        }
        Swap.swap(nums,start,slow);
        return slow;
    }

排序的时候,交换的不是结点的指针,而是交换链表结点的值,有点取巧。

    public ListNode sortList(ListNode head) {
        if(head==null||head.next==null) return head;
        quickSort(head,null);
        return head;
    }
    public void quickSort(ListNode begin,ListNode end){
        if(begin==end||begin.next==end) return;
        ListNode mid=partition(begin,end);
        quickSort(begin,mid);
        quickSort(mid.next,end);
    }
    public ListNode partition(ListNode begin,ListNode end){
        if(begin==end||begin.next==end) return begin;
        int key=begin.val;
        ListNode start=begin,next=begin.next;
        while(next!=end){
            if(next.val<key){
                start=start.next;
                swapVal(next,start);
            }
            next=next.next;
        }
        swapVal(begin,start);
        return start;
    }
    public void swapVal(ListNode p1,ListNode p2){
        int t=p1.val;
        p1.val=p2.val;
        p2.val=t;
    }

二、归并排序
单链表归并排序的思路是找到单链表的中间结点,并将链表从中间结点处断开得到两条单链表分别进行归并排序。注意这里需要将中间结点的前一个结点断开,并且中间结点是结点数除2的上界。如2个结点的链表中间结点是第2个,3个结点的链表中间结点是第二个,4个结点的链表中间点结是第3个。

    public static ListNode merge(ListNode head1,ListNode head2){
        if(head1==null) return head2;
        if(head2==null) return head1;
        ListNode start1=head1,start2=head2;
        ListNode head;
        if(start1.data.compareTo(start2.data)<0){
            head=start1;
            start1=start1.next;
        }else{
            head=start2;
            start2=start2.next;
        }
        head.next=merge(start1,start2);
        return head;
    }

    public static ListNode getMid(ListNode head){
        if(head==null||head.next==null) return head;
        ListNode fast=head.next.next;
        ListNode slow=head.next;
        ListNode pre=head;
        while(fast!=null&&fast.next!=null){
            slow=slow.next;
            fast=fast.next;
            if(fast.next!=null) fast=fast.next;
        }
        pre.next=null;
        return slow;
    }


    public static ListNode mergeSort(ListNode head){
        if(head==null||head.next==null) return head;
        ListNode head1=head;
        ListNode head2=getMid(head);
        head1=mergeSort(head1);
        head2=mergeSort(head2);
        return merge(head1,head2);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值