Home

LinkWorld Algorithm Blog

19 Feb 2018

单链表快速排序

一、题目

单链表实现快速排序法

二、解题思路

  • 假如链表结点依次为:0 69 51 71 10 40 79 99 78 43 89
  • 那么将根结点作为支点,同时维护三个子链表,left,right,mid
    • 循环链表,设当前循环到的结点为temp,头结点为head
      • 如果temp.value < head.value,就将结点插入到left中(第一次->{})
      • 如果temp.value > head.value,就将结点插入到right中(第一次->{69,51,71,10,40,79,99,78,43,89})
      • 如果temp.value = head.value,就将结点插入到mid中(第一次->{0})
    • 按照上述过程递归left和right子链表,并合并。
  • 参照地址:Java: 实现顺序表和单链表的快速排序

Kotlin实现

package Exercise

import java.util.*

fun main(args: Array<String>) {
    // 不为空
    val root = initLinkList()
    print("未排序之前:")
    print(root)
    println()
    print("排序完之后:")
    print(Solution().sortList(root))
    // 空
    println()
    print("未排序之前:")
    print(null)
    println()
    print("排序完之后:")
    print(Solution().sortList(null))
}

/**
 * 初始化单链表
 *
 * @return 返回单链表
 * */
fun initLinkList(): ListNode? {
    val random = Random()
    val root = ListNode(0, null)
    var temp: ListNode = root
    for (i in 1..10) {
        temp.next = ListNode(random.nextInt(100), null)
        temp = temp.next!!
    }
    return root
}

/**
 * 打印链表
 *
 * @param root 头结点
 * */
fun print(root: ListNode?) {
    if (root == null) return
    var result = root
    while (result != null) {
        print(result.value)
        print(" ")
        result = result.next
    }
}

class ListNode(var value: Int, var next: ListNode?)

class Solution {
    fun sortList(root: ListNode?): ListNode? {
        if (root?.next == null) return root
        var head = root
        // 左链表
        var left = ListNode(0, null)
        val leftHead = left
        // 右链表
        var right = ListNode(0, null)
        val rightHead = right
        // 中间链表
        var mid = ListNode(0, null)
        val midHead = mid
        // 支点的值
        val value = head.value

        /**
         * 快速排序,循环读取每一个链表结点,将其放在三个子链表中
         * */
        while (head != null) {
            when {
            // 如果小于支点,就放在左链表
                head.value < value -> {
                    left.next = head
                    left = head
                }
            // 如果大于支点,就放在右链表
                head.value > value -> {
                    right.next = head
                    right = head
                }
            // 如果等于,就放在中间链表
                else -> {
                    mid.next = head
                    mid = head
                }
            }
            head = head.next
        }

        left.next = null
        right.next = null
        mid.next = null
        return merge(this.sortList(leftHead.next), midHead.next, sortList(rightHead.next))
    }

    /**
     * 合并结点
     *
     * @param left 左结点
     * @param right 右结点
     * @param mid 中间结点
     * @return 返回头部结点
     * */
    private fun merge(left: ListNode?, mid: ListNode?, right: ListNode?): ListNode? {
        val leftTail = getTail(left)
        val midTail = getTail(mid)
        midTail!!.next = right
        return if (leftTail != null) {
            leftTail.next = mid
            left
        } else mid
    }

    /**
     * 获取链表的尾结点
     *
     * @param root 链表的头结点
     * @return 返回链表尾结点
     * */
    private fun getTail(root: ListNode?): ListNode? {
        if (root == null) return root
        var head = root
        while (head!!.next != null) {
            head = head.next
        }
        return head
    }
}

输出结果

未排序之前:0 69 51 71 10 40 79 99 78 43 89 
排序完之后:0 10 40 43 51 69 71 78 79 89 99 
未排序之前:
排序完之后:

Til next time,
LinkWorld at 10:41

scribble