快速排序算法原理:

设置分水岭,把小于分水岭的数排到分水岭左侧,其余的排到右侧,递归的对分水岭两侧的元素做同样的处理


package qsort

func quickSort(values []int, left int, right int) {
	if left < right {

		// 设置分水岭
		temp := values[left]

		// 设置哨兵
		i, j := left, right
		for {
			// 从右向左找,找到第一个比分水岭小的数
			for values[j] >= temp && i < j {
				j--
			}

			// 从左向右找,找到第一个比分水岭大的数
			for values[i] <= temp && i < j {
				i++
			}

			// 如果哨兵相遇,则退出循环
			if i >= j {
				break
			}

			// 交换左右两侧的值
			values[i], values[j] = values[j], values[i]
		}

		// 将分水岭移到哨兵相遇点
		values[left] = values[i]
		values[i] = temp

		// 递归,左右两侧分别排序
		quickSort(values, left, i-1)
		quickSort(values, i+1, right)
	}
}

func QuickSort(values []int) {
	quickSort(values, 0, len(values)-1)
}

更简洁的版本:

package main

import "fmt"

func main() {
   numbers := []int{6, 2, 7, 7, 3, 8, 9}
   //fmt.Println(numbers)
   QuickSort(numbers)

   fmt.Println(numbers)
}

func QuickSort(values []int) {
   length := len(values)
   if length <= 1 {
      return
   }
   mid, i := values[0], 1    // 取第一个元素作为分水岭,i下标初始为1,即分水岭右侧的第一个元素的下标
   head, tail := 0, length-1 // 头尾的下标

   // 如果头和尾没有相遇,就会一直触发交换
   for head < tail {
      fmt.Println(values, head, tail, i)
      if values[i] > mid {
         // 如果分水岭右侧的元素大于分水岭,就将右侧的尾部元素和分水岭右侧元素交换
         values[i], values[tail] = values[tail], values[i]
         tail-- // 尾下标左移一位
      } else {
         // 如果分水岭右侧的元素小于等于分水岭,就将分水岭右移一位
         values[i], values[head] = values[head], values[i]
         head++ // 头下标右移一位
         i++    // i下标右移一位
      }
      fmt.Printf("----{head:%d,tail:%d,i:%d,mid:%d} values:%v\n", head, tail, i, mid, values)
   }

   // 分水岭左右的元素递归做同样处理
   QuickSort(values[:head])
   QuickSort(values[head+1:])
}


更容易理解的版本

package main

import "fmt"

func main() {
    arr := []int{5, 4, 3, 6, 7, 8}
    rs := qsort(arr)
    fmt.Println(rs)
    // [3 4 5 6 7 8]
}

// 快速排序
func qsort(arr []int) []int {
    if len(arr) < 2 {
        return arr
    } else {
        pivot := arr[0]
        var less []int
        var greater []int
        for _, value := range arr[1:] {
            if value <= pivot {
                less = append(less, value)
            } else {
                greater = append(greater, value)
            }
        }

        var result []int
        result = append(result, qsort(less)...)
        result = append(result, pivot)
        result = append(result, qsort(greater)...)
        return result
    }
}