Go数据结构之队列与循环队列的实现

今天来教大家如何用Go实现一个队列和一个循环队列

一、普通队列

首先,我们需要知道队列的特点是什么,那就是:先进先出  

知道了这个特点之后,就可以进行代码的实现了,其实和上几期的数组,栈实现的差不多,唯一的区别在于 放入元素和取出元素的方式不同

1. 代码实现

话不多说,上代码:

package queue

type MyQueue[T any] interface {
	Size() int
	Front() T
	End() T
	IsEmpty() bool
	EnQueue(T)
	DeQueue() T
	Clear()
}

type Queue[T any] struct {
	dataStore []T
	theSize   int
}

func NewQueue[T any]() MyQueue[T] {
	return &Queue[T]{
		theSize:   0,
		dataStore: make([]T, 0),
	}
}

func (q *Queue[T]) Size() int {
	return q.theSize
}

// Front 第一个元素
func (q *Queue[T]) Front() T {
	if q.theSize == 0 {
		var zero T
		return zero
	}
	return q.dataStore[0]
}

// End 最后一个元素
func (q *Queue[T]) End() T {
	if q.theSize == 0 {
		var zero T
		return zero
	}
	return q.dataStore[q.theSize-1]
}

func (q *Queue[T]) IsEmpty() bool {
	return q.theSize == 0
}

func (q *Queue[T]) EnQueue(data T) {
	q.dataStore = append(q.dataStore, data)
	q.theSize++
}

func (q *Queue[T]) DeQueue() T {
	if q.theSize == 0 {
		var zero T
		return zero
	}
	last := q.dataStore[0]
	if q.theSize > 0 {
		q.dataStore = q.dataStore[1:q.theSize]
	} else {
		q.dataStore = make([]T, 0)
	}
	q.theSize--
	return last
}

func (q *Queue[T]) Clear() {
	q.dataStore = make([]T, 0)
	q.theSize = 0
}

相信应该没什么问题,无非是方法的定义可能会有些许区别。

二、循环队列(环形队列)

环形队列的要点在于,他是一个圆,我们需要两个类似指针的东西,来指示我现在的队列里面有多少元素,以及判断空与满的状态

其次,环形队列的实际大小会少一个,因为两个用来指示的 front 和 rear,当它们相等的时候,就为空,而满的状态,我们需要留出一个空间才能实现判断,rear + 1 = front 的时候,就是满。

所以,当我们不断加入元素,rear 就会不断增加,直到满。当我们不断取出元素,front 就会从 0 开始 不断增加,因为队列的特点是先进先出。

1. 代码实现

package circleQueue

import "errors"

// QueueSize 实际大小只有99个,因为需要留出一个用来表示满状态
const QueueSize = 100

// CircleQueue 环形队列,也叫循环队列
type CircleQueue[T any] struct {
	data  [QueueSize]T
	front int // 头部
	rear  int // 尾部
}

func initQueue[T any](q *CircleQueue[T]) {
	// 环形时 头尾重合表示空
	q.front = 0
	q.rear = 0
}

// QueueLength 计算长度
func QueueLength[T any](q *CircleQueue[T]) int {
	// 这么做是为了防止当 front > rear的时候,会出现负数
	return (q.rear - q.front + QueueSize) % QueueSize
}

// EnQueue 入队
func EnQueue[T any](q *CircleQueue[T], data T) error {
	if (q.rear+1)%QueueSize == q.front%QueueSize {
		return errors.New("队列已满")
	}
	q.data[q.rear] = data
	q.rear = (q.rear + 1) % QueueSize
	return nil
}

// DeQueue 出队
func DeQueue[T any](q *CircleQueue[T]) (T, error) {
	var zero T
	if q.front == q.rear {
		return zero, errors.New("队列为空")
	}

	res := q.data[q.front]
	q.data[q.front] = zero

	q.front = (q.front + QueueSize) % QueueSize
	return res, nil
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值