排序算法工程实践 |青训营笔记

93 阅读2分钟

引言

想到排序,是否就跳出了数据结构课上的记忆,基数排序,堆排序,快速排序,插入冒泡排序,希尔排序... 对于这些算法,往往课堂上只是抛出了算法实现方式,分析时间复杂度,空间复杂度,稳定性,也可能有部分改进算法,考察就是硬问这几种排序,没有情景,要求写哪种排序算法就是哪种. 学校很纯粹,但生活不一定. 之前的go实战,需求上线的字节课程已经见识了防御编程,分布式,微服务架构的开发流程,所以排序算法是面向生产的,必须考虑效率和成本! benchmark.jpg 直观感受下排序的工程选择


v1.jpg

实践

首先是熟悉的插入算法InsertionSort

func insertionSort(data interface ,a,b int){
   for i := 0; i < b; i++{
          for j := i ; j > a&&data.Less(j,j-1) ; j--{
			data.Swap(j , j-1)
		  }
     }
}

根据基准测试,短序列采用插入排序比较快.根据工程实践经验,字节长度24内算短序列.

堆排序:很稳定的算法heapSort

func siftDown(data Interface, lo, hi, first int) {
	root := lo
	for {
		child := 2*root + 1
		if child >= hi {
			break
		}
		if child+1 < hi && data.Less(first+child, first+child+1) {
			child++
		}
		if !data.Less(first+root, first+child) {
			return
		}
		data.Swap(first+root, first+child)
		root = child
	}
}

func heapSort(data Interface, a, b int) {
	first := a
	lo := 0
	hi := b - a

	// Build heap with greatest element at top.
	for i := (hi - 1) / 2; i >= 0; i-- {
		siftDown(data, i, hi, first)
	}

	// Pop elements, largest first, into end of data.
	for i := hi - 1; i >= 0; i-- {
		data.Swap(first, first+i)
		siftDown(data, lo, i, first)
	}
}


升序排序采用堆排序的基本原理是:建立一个小顶堆(就是父节点始终比子节点小的完全二叉树),每次把堆顶的元素取出来就成了一个升序的序列. 代码中创建堆使用循环中调用shiftdown函数,即从最后一个叶节点向上遍历,不断调整.

快速排序 QuickSort

func quickSort(arr []int, left int, right int) {
    if left < right {
        pivotIndex := partition(arr, left, right)
        quickSort(arr, left, pivotIndex-1)
        quickSort(arr, pivotIndex+1, right)
    }
}
//
func partition(arr []int, left int, right int) int {
    pivot := arr[right]
    i := left - 1
    for j := left; j < right; j++ {
        if arr[j] < pivot {
            i++
            arr[i], arr[j] = arr[j], arr[i]
        }
    }
    i++
    arr[i], arr[right] = arr[right], arr[i]
    return i
}

其中,quickSort函数采用递归的方式进行快速排序,partition函数用于将数组划分为左右两部分。在partition函数中,选取数组最后一个元素作为pivot元素,并将小于pivot元素的元素放在数组左侧,大于pivot元素的元素放在数组右侧。最后返回pivot元素的位置即可。

最后来个总结

排序.jpg

mindmap
      sort
          插入n n^2
          快速
          堆排序Heap稳!
          pdq混合排序算法
    
          情况
           随机序列
             短序列数据插入排序
             其他用快排
            

总结:

  • pdq从选择到优化
  • 使用插入排序短序列
  • 极端情况堆排序 保证算法可行性
  • 完全随机的情况 pivot取近似中位数

然后呢...

  • 重复数很多的情况
  • 新的pdq排序算法 实现第一个版本...

人生三省,吾常思图省身之事 下篇文章见🍻

参考

pdq算法原论文

讲师的排序算法代码库