介绍
与栈一样,队列也是最基本的数据结构之一。队列也是值的一种容器,其中值的插入和删除遵循“先进先出”(First-In-First-Out, FIFO)的原则⎯⎯也就是说,每次删除的只能是最先插入的值。
实现
队列的抽象数据类型就是一个数组,其中的值排成一个序列,我们只能访问和取出排在最前端(Front)的对象,只能在队列的尾部(Rear)插入新值。正是按照这一规则,才能保证最先被插入的对象首先被删除(FIFO)。
队列首先支持下面的两个基本方法:
此外,与栈类似,队列还支持如下的方法:
基于数组的简单实现
我们使用一个数组来模拟队列,队列的数据结构定义如下:
type T inttype Queue struct {sync.RWMutexarray []T
}
我们依次去实现队列的方法,对于进队Enqueue()方法,直接利用go原生语句将值添加到数组切片中。
// Enqueue adds t to the end of the queue
func (q *Queue) Enqueue(t T) {q.Lock()q.array = append(q.array, t)q.Unlock()
}
出队Dequeue()和取队首元素Front()时注意数组空判断。
// Dequeue removes the start of from the queue
func (q *Queue) Dequeue() (error, *T) {q.Lock()if len(q.array) == 0 {q.Unlock()return fmt.Errorf("queue is empty"), nil}ret := q.array[0]q.array = q.array[1:len(q.array)]q.Unlock()return nil, &ret
}// Front returns the start in the queue, without removing it
func (q *Queue) Front() (error, *T) {q.Lock()if len(q.array) == 0 {q.Unlock()return fmt.Errorf("queue is empty"), nil}ret := q.array[0]q.Unlock()return nil, &ret
}
剩下Size()以及IsEmpty()即对队列的数组大小进行判断取值。
// Size returns the size of the queue
func (q *Queue) Size() int {q.RLock()defer q.RUnlock()return len(q.array)
}// IsEmpty returns true if the queue is empty
func (q *Queue) IsEmpty() bool {q.RLock()defer q.RUnlock()return len(q.array) == 0
}
单元测试
这里测试进队和出队方法:
import "testing"var (t1 T = 1t2 T = 2t3 T = 3
)func TestQueue_Enqueue(t *testing.T) {queue := NewQueue()queue.Enqueue(t1)queue.Enqueue(t2)queue.Enqueue(t3)if size := queue.Size(); size != 3 {t.Errorf("wrong count, expected 3 and got %d", size)}
}func TestQueue_Dequeue(t *testing.T) {queue := NewQueue()queue.Enqueue(t1)queue.Enqueue(t2)queue.Enqueue(t3)_, ret := queue.Dequeue()if *ret != t1 {t.Errorf("wrong result, expected %d and got %d", *ret, t1)}_, _ = queue.Dequeue()_, ret = queue.Dequeue()if *ret != t3 {t.Errorf("wrong result, expected %d and got %d", *ret, t3)}err, _ := queue.Dequeue()if !queue.IsEmpty() {t.Errorf("IsEmpty should return true")}if err == nil {t.Errorf("cannot operate dequeue when queue is empty")}
}
至此,单元测试通过,我们就完成了队列数据结构的实现。