leetcode:單鏈表的排序

//鏈表結構

 class ListNode {
	int val;
    ListNode next;
    ListNode(int x) {
     val = x;
    next = null;
 }

單鏈表的插入排序

    //鏈表的插入排序
    public ListNode insertionSortList(ListNode head) {
        //非空判斷 頭結點爲空或者
        if(head==null||head.next==null)
        {
            return head;
        }
        //建立一個僞頭結點 便於頭結點的替換
        ListNode unrealHead=new ListNode(Integer.MIN_VALUE);
        unrealHead.next=head;//連接到頭結點上
        ListNode curSortedIndex=head;//當前有序位置
        ListNode nextSortIndex=head.next;//下一個需要進行排序的位置
        //鏈表的排序不同於數組的排序  可以直接從頭部開始查找 不需要向數組那樣從有序位置向前查找 以簡化操作
        while(nextSortIndex!=null)//仍有待排序的元素
        {
            //大於已經排序好鏈表的最大值
            if(nextSortIndex.val>=curSortedIndex.val)//不需要變動位置
            {
                curSortedIndex=nextSortIndex;
                nextSortIndex=nextSortIndex.next;
            }
            else
            {
                //從頭開始查找
                ListNode curNode=unrealHead;
                while(curNode.next.val<=nextSortIndex.val)
                {
                    curNode=curNode.next;
                }
                //curNode指向的下一個元素已經大於nextSortIndex
                //將nextSortIndex連接在curNode之後
                ListNode assistNode=nextSortIndex;//輔助節點 記錄要插入的元素
                nextSortIndex=nextSortIndex.next;//下一排序位置後移
                curSortedIndex.next=nextSortIndex;//將斷開的鏈搭上
                
                //元素插入指定位置
                assistNode.next=curNode.next;
                curNode.next=assistNode;
            }
        }
        //排序完成 返回真正的頭結點 
        return unrealHead.next;
    }

單鏈表的歸併排序

/**************
* 歸併排序的實現 最終要的在於實現二路歸併的算法
* 分成兩個部分 對左半部分進行歸併排序 對右半部分進行歸併排序
* 左右部分進行二路歸併
**************/
    public ListNode sortList(ListNode head) {
        //鏈表長度判斷
        if(head==null||head.next==null)
        {
            return head;
        }
        ListNode midNode=findMidNode(head);
        ListNode rightFirst=midNode.next;
        midNode.next=null;
        ListNode leftHead=sortList(head);
        ListNode rightHead=sortList(rightFirst);
        
        return mergeList(leftHead,rightHead);
    }
    /******************
    * 查找鏈表的中間位置 並返回
    * 查找思路爲使用兩個引用 一個一次後移兩格(快指針),一個一次後移一格(慢指針)
    * 當快指針走到結尾時,慢指針正好走到中間位置
    * 
    *鏈表節點個數爲偶數2n時,fast走到空時 ,slow在n位置
    *鏈表節點爲奇數2n+1時,fast.next爲空時,slow在n的位置
    *將鏈表分爲兩半時,中間節點分到前半部分
    **************/
    private ListNode findMidNode(ListNode head)
    {
        //爲空或只有一個節點
        if(head==null||head.next==null)
        {
            return head;
        }
       //定義快節點和慢節點
        ListNode fastNode=head.next;
        ListNode slowNode=head;
        //直到快節點走到null或者快節點的下一個節點爲null
        while(fastNode!=null&&fastNode.next!=null)
        {
            fastNode=fastNode.next.next;
            slowNode=slowNode.next;
        }
        //返回中間位置節點
        return slowNode;
    }
    /********************
    * 鏈表的二路歸併
    * 返回連接後的頭節點 類似多項式的合併
    ********************/
    private ListNode mergeList(ListNode first,ListNode second)
    {
        //左邊爲空 直接返回
        if(first==null)
        {
            return second;
        }
        if(second==null)
        {
            return first;
        }
        ListNode curFirst=first;
        ListNode curSecond=second;
        //找尋頭節點 使用first存儲 second節點用於
        if(first.val<second.val)
        {
            curFirst=curFirst.next;//指針後移
        }
        else
        {
            first=second;
            curSecond=curSecond.next;
        }
        second=first;//已成鏈的最後一個節點
        //循環查找 將節點搭在鏈上
        while(curFirst!=null&&curSecond!=null)
        {
            if(curFirst.val<curSecond.val)
            {
                second.next=curFirst;//將first連接在節點之後
                curFirst=curFirst.next;//first指針後移 指向下一個
            }
            else
            {
                second.next=curSecond;
                curSecond=curSecond.next;
            }
            second=second.next;//鏈尾新加入一個節點
        }
        //判斷哪條鏈遍歷完成
        if(curFirst==null) second.next=curSecond;
        else
        {
            second.next=curFirst;
        }
        //返回頭結點
        return first;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章