链表实现快排和归并

题目连接:https://leetcode.cn/problems/sort-list/

 

 

快排(使用快排容易超时,建议使用归并排序)

func main(){
    head:=&ListNode{}
    end:=head
    aaa:=0
    for i:=0;i<6;i++{
        if i%2==0{
            aaa=i
        }else{
            aaa=-1*i
        }
        tmp:=&ListNode{
            Val: aaa,
            Next: nil,
        }
        end.Next=tmp
        end=tmp
    }
    quicksort(head.Next,end)
    head=head.Next
    for head!=nil{
        fmt.Printf("%v ",head.Val)
        head=head.Next
    }
}
type ListNode struct{
    Val int
    Next *ListNode
}

func quicksort(head,end *ListNode){
    if head == nil || head == end{
        return
    }
    //找基准元素
    le , ri := head, head.Next
    base := le.Val
    for ri != nil{ //从右边开始处理,将比base小的元素交换到右边
        if ri.Val < base{   //不能取等号
            le = le.Next
            le.Val , ri.Val = ri.Val,le.Val
        }
        ri = ri.Next
    }
    head.Val , le.Val = le.Val,head.Val  //[head,le],[le.Next,end]
    quicksort(head,le)
    quicksort(le.Next,end)
}

 

 

归并

type ListNode struct{
    Val int
    Next *ListNode
}
func main(){
    head:=&ListNode{}
    end:=head
    aaa:=0
    for i:=0;i<6;i++{
        if i%2==0{
            aaa=i
        }else{
            aaa=-1*i
        }
        tmp:=&ListNode{
            Val: aaa,
            Next: nil,
        }
        end.Next=tmp
        end=tmp
    }
    h:=sortList(head.Next)
    for h!=nil{
        fmt.Printf("%v ",h.Val)
        h=h.Next
    }
}
func sortList(head *ListNode) *ListNode {
    if head == nil || head.Next == nil { // 递归的出口,不用排序 直接返回
        return head
    }
    slow, fast := head, head // 快慢指针将链表对半分
    var preSlow *ListNode    // 保存slow的前一个结点
    for fast != nil && fast.Next != nil {
        preSlow = slow
        slow = slow.Next      // 慢指针走一步
        fast = fast.Next.Next // 快指针走两步
    }
    preSlow.Next = nil  // 断开,分成两链
    le := sortList(head) // 已排序的左链
    ri := sortList(slow) // 已排序的右链
    return mergeList(le, ri) // 合并已排序的左右链,一层层向上返回
}

func mergeList(le, ri *ListNode) *ListNode {
    newHead := &ListNode{Val: 0}   // 虚拟头结点
    end := newHead                // 合并后的尾结点,这里使用尾插法合并链表
    for le != nil && ri != nil { // le ri 都存在
        if le.Val < ri.Val {   // le值较小
            end.Next = le // end.Next指向le
            le = le.Next   // 考察le的下一个结点
        } else {
            end.Next = ri
            ri = ri.Next
        }
        end = end.Next // end.Next确定了,尾指针推进
    }
    if le != nil {    // le存在,ri不存在,让end.Next指向le
        end.Next = le
    }
    if ri != nil {
        end.Next = ri
    }
    return newHead.Next // 真实头结点
}

 

 
posted @ 2022-06-21 22:31  知道了呀~  阅读(117)  评论(0编辑  收藏  举报