• 堆技术细节与堆排序【原创】


    参考:

    https://www.jianshu.com/p/6b526aa481b1(数据结构:堆)

    https://www.runoob.com/w3cnote/heap-sort.html(堆排序)

    堆的性质

    堆是具有以下性质的完全二叉树,每个节点的值都大于或等于其左右孩子节点的值称为最大堆,反之为最小堆。

    注意:没有要求节点的左孩子的值和右孩子的值的大小关系。

    堆的存储

    1,堆使用数组实现,不是结点和指针。
    2,堆的属性可以让堆和数组元素直接对应起来

    这个数组arr逻辑上就是一个堆。

    从这里我们可以得出以下性质(重点)

    对于大顶堆:arr[i] >= arr[2i + 1] && arr[i] >= arr[2i + 2]

    对于小顶堆:arr[i] <= arr[2i + 1] && arr[i] <= arr[2i + 2]

    堆结点与数组小标关系:

    1,index从0开始

    2,父节点为 i,左节点:2i+1;右结点:2i+2

    3,子节点为 i,floor( (i-1)/2) 等价于 (i-1)>>1

    核心操作

    上浮操作

    当前结点与父节点比较,小于父节点则交换(最小堆情况下,最大堆相反),递归向上

    func HeapUp(arr []int,index int)  {
    
        for pi:=(index-1)>>1;index>0;pi=(index-1)>>1{
            piv:=arr[pi]//切片本身是引用型
            iv:=arr[index]
            if piv>iv{
                arr[index],arr[pi] = arr[pi],arr[index]
            }else {
                break
            }
            index=pi
        }
        //return arr
    }
    //test
    arr:=[]int{5,3,6,4,7,2}
    HeapUp(arr,len(arr)-1)
    fmt.Println(arr)

    下沉操作

    当前结点与左右子节点比较,大于较小的节点则交换(最小堆的情况下,最大堆是小于较大的节点),递归向下

    func HeapDown(arr []int,index int)  {
        for li,ri :=2*index+1,2*index+2;ri<len(arr); li,ri =2*index+1,2*index+2{//第3句pi=(index-1)>>1不能省略,这里涉及到for循环的本质
            liv:=arr[li]//切片本身是引用型
            riv:=arr[ri]
            iv:=arr[index]
            small:=liv
            si:=li
            if small>riv{
                small = riv
                si=ri
            }
            if iv>small{
                arr[index],arr[si] = arr[si],arr[index]
                fmt.Println(index,si)
            }else {
                break
            }
            index=si
        }
    }
    //测试
    arr:=[]int{9,5,3,6,4,7,2}
    HeapDown(arr,0)
    fmt.Println(arr)

    插入

    1,先把元素插入到末尾

    2,使用上浮操作,对插入的尾部元素

    删除:最小头元素

    1,将头尾元素交换

    2,删除交换后的尾部元素

    3,使用下层操作,对交换后的呕吐不元素

    获取

    直接获取小标为0的元素

    堆排序

    堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),是不稳定排序

    算法步骤

    1. 创建一个堆 H[0……n-1];

    2. 把堆首(最大值)和堆尾互换;

    3. 把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;

    4. 重复步骤 2,直到堆的尺寸为 1。

    show me the code

    func heapSort(arr []int) []int {
            arrLen := len(arr)
            buildMaxHeap(arr, arrLen)
            for i := arrLen - 1; i >= 0; i-- {
                    swap(arr, 0, i)
                    arrLen -= 1
                    heapify(arr, 0, arrLen)
            }
            return arr
    }
    
    func buildMaxHeap(arr []int, arrLen int) {
            for i := arrLen / 2; i >= 0; i-- {
                    heapify(arr, i, arrLen)
            }
    }
    
    func heapify(arr []int, i, arrLen int) {
            left := 2*i + 1
            right := 2*i + 2
            largest := i
            if left < arrLen && arr[left] > arr[largest] {
                    largest = left
            }
            if right < arrLen && arr[right] > arr[largest] {
                    largest = right
            }
            if largest != i {
                    swap(arr, i, largest)
                    heapify(arr, largest, arrLen)
            }
    }
    
    func swap(arr []int, i, j int) {
            arr[i], arr[j] = arr[j], arr[i]
    }
  • 相关阅读:
    公司要上监控,Zabbix 和 Prometheus 怎么选?这么选准没错!
    60 个神级 VS Code 插件!!
    Elasticsearch 实现分页的 3 种方式,还有谁不会??
    紫微斗数是否对外国人有用
    Cygwin 安装时提示 “Could not download mirror sites list” 处理方法
    win 窗体 按钮 .Enabled:=false 中间做很多事情 还是会触发clik事件思考
    Docker Buildx使用教程:使用Buildx构建多平台镜像
    【问题解决】Alpine镜像中执行jstack、arthas等命令提示Unable to get pid of LinuxThreads manager thread
    MongoDB 远程连接配置
    星环TDHsearch启动失败master not discovered exception解决
  • 原文地址:https://www.cnblogs.com/tkzc2013/p/16326994.html
Copyright © 2020-2023  润新知