2010-08-12 77 views
2

基於Rob Pike的load balancer demo,我實現了我自己的優先級隊列,但是我的Pop方法不對,任何人都可以告訴我什麼是錯的?我的Priority Queue的Pop方法有什麼問題?

package main 

import (
    "fmt" 
    "container/heap" 
) 

type ClassRecord struct { 
    name string 
    grade int 
} 

type RecordHeap []*ClassRecord 

func (p RecordHeap) Len() int { return len(p) } 

func (p RecordHeap) Less(i, j int) bool { 
    return p[i].grade < p[j].grade 
} 

func (p *RecordHeap) Swap(i, j int) { 
    a := *p 
    a[i], a[j] = a[j], a[i] 
} 

func (p *RecordHeap) Push(x interface{}) { 
    a := *p 
    n := len(a) 
    a = a[0 : n+1] 
    r := x.(*ClassRecord) 
    a[n] = r 
    *p = a 
} 

func (p *RecordHeap) Pop() interface{} { 
    a := *p 
    *p = a[0 : len(a)-1] 
    r := a[len(a)-1] 
    return r 
} 

func main() { 
    a := make([]ClassRecord, 6) 
    a[0] = ClassRecord{"John", 80} 
    a[1] = ClassRecord{"Dan", 85} 
    a[2] = ClassRecord{"Aron", 90} 
    a[3] = ClassRecord{"Mark", 65} 
    a[4] = ClassRecord{"Rob", 99} 
    a[5] = ClassRecord{"Brian", 78} 
    h := make(RecordHeap, 0, 100) 
    for _, c := range a { 
     fmt.Println(c) 
     heap.Push(&h, &c) 
     fmt.Println("Push: heap has", h.Len(), "items") 
    } 
    for i, x := 0, heap.Pop(&h).(*ClassRecord); i < 10 && x != nil; i++ { 
     fmt.Println("Pop: heap has", h.Len(), "items") 
     fmt.Println(*x) 
    } 
} 

編輯:除了cthom06的方式指出,另一種方式來解決這個問題如下:創建一個指針數組,

a := make([]*ClassRecord, 6) 
a[0] = &ClassRecord{"John", 80} 
a[1] = &ClassRecord{"Dan", 85} 
...... 

回答

1

編輯:

哦,我應該馬上看到了這一點。

heap.Push(&h, &c) 

您推送c的地址,該地址在範圍的每次迭代中得到重用。堆中的每條記錄都是指向內存中同一區域的指針,最終成爲Brian。我不確定這是預期行爲還是編譯器錯誤,但是

t := c 
heap.Push(&h, &t) 

解決它。

另外:你的for循環是錯誤的。

for h.Len() > 0 { 
    x := heap.Pop(&h... 

應該修復它。

+0

就是這樣。謝謝。 – grokus 2010-08-12 19:02:03

+0

我增加了另一種方法來解決這個問題。通過使用指針數組,我可以避免複製結構。謝謝。 – grokus 2010-08-12 20:07:37

+0

@grokus更好 – cthom06 2010-08-12 20:21:27