golang 堆排序(TopK)


堆排序可以很好解決TopK問題

時間復雜度 N(logN),不穩定排序,相同大小數據仍可能交換位置

尋找海量數據中最大的100個數據,可以建立容量100的小頂堆,然后將后面的數據與堆頂最小值比較,

如果比它大,進行交換重新將堆進行調整,后面數據以此類推,可以得到top 100的數據

 

package main

import "fmt"

//想得到從小到大的排序結果,需要構建大頂堆,然后將堆頂最大值與最后的數據交換,
//依次進行,可以得到順序的結果
func HeapSort(nums []int)  {
	
	N:=len(nums)-1
	//從底部到頂部構建大頂堆,最后一個非葉子節點開始
	for i:=N/2-1;i>=0;i--{   //減少1才是最后一個非葉子節點。
		sink(nums,i,N)
	}
	
	//將堆頂值和末尾交換,重新調整堆
	for i:=N;i>=0;i--{
		wap(nums,0,i)
		sink(nums,0,i-1)//交換之后,數組最后一位不算在堆內,需要減1操作
	}
	
	//不同寫法,結果一樣
	/*for N>=0{
		wap(nums,0,N)
		N--
		sink(nums,0,N)
	}*/
}

func sink(nums []int,k,N int)  {
	for{
		i:=2*k+1
		if i>N{
			break
		}
		//找左右子節點最大值
		if i+1<=N&&nums[i+1]>nums[i]{
			i++
		}
		//已經大於最大值,不需要再交換
		if nums[k]>=nums[i]{
			break
		}
		wap(nums,k,i)
		k = i //繼續向上調整
	}
}

func wap(nums []int,x,y int){
	nums[x],nums[y] = nums[y],nums[x]
}

func main()  {
	s := []int{-1,9, 0, 6, 5, 8, 2, 1, 7, 4, 3}
	fmt.Println(s)
	HeapSort(s)
	fmt.Println(s)
}

  

 

TopK問題,一億數據找最大10000

建立10000的最小堆,數據依次放入堆,比堆頂大則互換下沉,建堆O(nlogn)  總時間復雜 O(mnlogn)  m=一億  n=10000

下面簡單例子

//TopK問題 //維護小頂堆,比最小的大,放頭部下沉,最終得到topK
func sink(array []int,start,length int) { for{ //2*n+1 可以畫圖就知道為什么了,是左邊子節點
        next:=2*start+1
        if next>length{ break } if next+1<=length&&array[next+1]<array[next]{ next++ } //上層小於下面,不用互換了
        if array[start]<=array[next]{ break } //互換繼續下沉
        array[start],array[next] = array[next],array[start] start = next } } func main() { array:=[]int{2,1,5,8,5,6,3,2,7} //tok 5
    res:=make([]int,5) for _,v:=range array{ if v<=array[0]{ continue } res[0] = v sink(res,0,4) } fmt.Println(res) }

 

還可以分別放在1000個文件分別找到前10000然后合並排序。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM