優先級隊列實現


優先級隊列的底層實現是堆(最大堆、最小堆)

一、堆的特點

  1. 完全二叉樹
  2. 每個節點的值都必須大於等於或小於等於子樹中節點的值(對應最大堆、最小堆)
  3. 往堆中插入和刪除一個元素的時間復雜度都是O(logn)

二、實現

最大堆和最小堆實現原理基本一樣,下面實現一個最大堆

package main

type MaxHeap struct {
   array []int //數組,從下標1開始存儲數據
   count int   //堆中已經存儲的數據個數
   size  int
}

//初始化一個堆
func NewMaxHeap(size int) *MaxHeap {
   obj := &MaxHeap{
      size:  size,
      count: 0,
      array: make([]int, size),
   }
   return obj
}

//往堆中添加一個元素
func (this *MaxHeap) Push(data int) bool {
   if this.count >= this.size {
      return false
   }
   this.array[this.count] = data
   i := this.count
   this.dowToUp(i)
   this.count++
   return true
}

//移除堆頂元素
func (this *MaxHeap) Pop() int {
   if this.count == 0 {
      return -1 //堆中沒有數據
   }
   max := this.array[0]
   this.array[0] = this.array[this.count-1] //將最后一個元素放到堆頂
   this.count--
   this.upToDown(0) //堆化
   return max
}

//獲取當前存儲元素的個數
func (this *MaxHeap) Count() int {
   return this.count
}

//從下往上堆化
func (this *MaxHeap) dowToUp(i int) {
   for (i-1)/2 >= 0 && this.array[i] > this.array[(i-1)/2] {
      this.swap(i, (i-1)/2)
      i = (i - 1) / 2
   }
}

//自上往上堆化
func (this *MaxHeap) upToDown(i int) {
   for {
      a := this.array
      n := this.count
      maxPos := i

      leftNode := i*2 + 1
      rightNode := i*2 + 2

      if leftNode < n && a[i] < a[leftNode] {
         maxPos = leftNode
      }
      if rightNode < n && a[maxPos] < a[rightNode] {
         maxPos = rightNode
      }
      if maxPos == i {
         break
      }
      this.swap(i, maxPos)

      i = maxPos //再檢測子節點
   }
}

func (this *MaxHeap) swap(i int, j int) {
   this.array[i], this.array[j] = this.array[j], this.array[i]
}

這個最大堆本質就是一個優先級從高到低的隊列,下面是測試

func main() {
   //待入隊元素
   a := []int{8, 7, 6, 9, 0, 5, 1, 2, 3, 4}

   //new一個優先級隊列
   priorityQueue := NewMaxHeap(len(a))
   for i := 0; i < len(a); i++ {
      priorityQueue.Push(a[i]) //依次入隊
   }

   //依次出隊
   for priorityQueue.Count() > 0 {
      fmt.Print(priorityQueue.Pop(), " ")
   }
}

輸出

9 8 7 6 5 4 3 2 1 0 

三、堆排序

1.每次將堆中最大的元素移到數組的末尾
2.剩下n-1個元素重新堆化
3.重復到此過程至下標1的元素


func NewMaxHeadByArray(a []int) *MaxHeap {
 n := len(a)
 obj := &MaxHeap{
  array: a,
  count: n,
  size: n,
 }
 //堆化
 for i := n / 2; i >= 0; i-- {
  obj.upToDown(i)
 }
 return obj
}

//堆排序
func MaxHeapSort(a []int) {
 heap := NewMaxHeadByArray(a)
 for heap.count > 0 {
  //將最大的元素移到數組最后
  heap.array[0], heap.array[heap.count-1] = heap.array[heap.count-1], heap.array[0]
  //減少堆的長度
  heap.count--
  //堆頂元素改變,重新堆化,保持堆的特性
  heap.upToDown(0)
 }
}

測試

func main() {
 //待入隊元素
 a := []int{8, 7, 6, 9, 0, 5, 1, 2, 3, 4}
 MaxHeapSort(a)
 fmt.Println(a)
}

輸出

[0 1 2 3 4 5 6 7 8 9]

堆排序的復雜度為O(nLogn)


免責聲明!

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



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