什麼是堆?
堆是一棵完全二叉樹,並滿足
(大頂堆)
或者
(小頂堆)
數組存儲
堆可以做什麼?
可以用來排序,可以用來找到第k大元素
//另注意golang有原生的容器heap //import "container/heap" package main import "fmt" //加入,加入元素到最後,然後上浮操作 func add(nums[]int,val int)[]int{ nums=append(nums,val) for i:=len(nums)-1;i>0;i--{ if nums[i]>nums[(i-1)/2]{ tmp:=nums[i] nums[i]=nums[(i-1)/2] nums[(i-1)/2]=tmp } } return nums } func del(nums[]int)int{ //刪除,將根和最後的元素交換,然後下沉操作 s:=len(nums)-1 max:=nums[0];nums[0]=nums[s];nums[s]=max for i:=0;i<s;{ l:=2*i+1;r:=2*i+2;k:=l if l<s&&r<s&&nums[l]<nums[r]{ k=r } if k<s&&nums[k]>nums[i]{ tmp:=nums[i];nums[i]=nums[k];nums[k]=tmp i=k }else{ break } } return max } func main(){ nums:=[]int{4,6,8,5,9} var bigHead []int for i:=0;i<len(nums);i++{ bigHead=add(bigHead,nums[i]) } fmt.Println(bigHead) fmt.Println(del(bigHead)) fmt.Println(bigHead) //去除最後一個 bigHead=bigHead[:len(bigHead)-1] fmt.Println(del(bigHead)) fmt.Println(bigHead) }
//以下是按堆的模式寫的程序 //最終是堆,但太浪費了,堆只需要添加和刪除兩個操作 //並且,以爲已經有序,會保持堆的特性,而無序遞歸檢查 package main import "fmt" //遞歸監測,交換到底 func change(nums []int,i,j int){ s:=j if i>=s{ return } l:=2*i+1 if l<s{ if nums[l]>nums[i] { tmp := nums[l] nums[l] = nums[i] nums[i] = tmp } change(nums, l,j) } r:=2*i+2 if r<s{ if nums[r]>nums[i] { tmp := nums[r] nums[r] = nums[i] nums[i] = tmp } change(nums, r,j) } } //從最後一個非葉節點,換到頂 func build(nums []int)[]int{ s:=len(nums) for i:=s/2-1;i>=0;i--{ //對於非葉節點,要遍歷到葉子,檢查是否滿足 change(nums,i,s) } return nums } //堆排序 func findAllMax(nums[]int)[]int{ s:=len(nums) for i:=s-1;i>0;i--{ tmp:=nums[i] nums[i]=nums[0] nums[0]=tmp change(nums,0,i) } return nums } func main(){ bigHead:= build([]int{4,6,8,5,9}) fmt.Println(bigHead) fmt.Println(findAllMax(bigHead)) } /* [9 6 8 4 5] [4 5 6 8 9] */