队列的实现

1、实现目标

通过Java和Golang两种语言实现队列,此处的队列的满足的要求有:

  • 长度需要设定,也即长度固定
  • 满足队列的基本要求,先进先出
  • 存放的类型自定义,Java通过泛型实现,Golang暂定用interface{}

完整代码和测试代码,参考:https://github.com/lzj09/data-structure

2、实现逻辑

对于Java,内部是通过数组来实现;

对于Golang,内部是通过切片来实现;

同时内部有2个索引,分别用于指向队头和队尾的下一个下标,即:

  • 指向队头的下标用front表示
  • 指向队尾的下一个下标用rear表示,这里需要注意,这是为了方便下标进行循环,也即为了方便取模运算,特意让rear指向队尾的下一个下标,这也即意味着,队列中总有一个位置是存不了数据的,所以队列长度为n时,实质队列的长度需要为n+1

如图所示,队列的加入数据和获取数据的过程:
在这里插入图片描述
上图所演示的队列最大存放数据量为3的队列(实质队列的长度需要4)过程,从上图可以得如下结论:

  • 当front==rear时,表示队列为空

  • 当加入数据时,数据加入的下标为rear,同时rear需要下移,需要考虑循环,则rear的下移算法为:

    rear = (rear + 1) % size

  • 当取数据时,数据取front对应的数据,同时front也需要下移,也需要考虑循环,front的下移算法为:

    front = (front + 1) % size

  • 当队列满时的条件,即为:(rear - front + 1) % size == 0

3、代码实现

Java版本:

package com.github.lzj09.datastructure.queue;

/**
 * 基于数组实现队列
 * 
 * @author lzj
 * @date 2022-11-29
 */
public class ArrayQueue<T> {
	// 指向队头的下标
	private int front;
	
	// 指向队尾的下标下一个下标
	private int rear;
	
	// 队列的最大容量
	private int size;
	
	// 存放数据的数组容器
	private T[] arrs;

	@SuppressWarnings("unchecked")
	public ArrayQueue(int size) {
		// 由于rear指向队尾的下一个下标,为此需要多1个空间
		this.size = size + 1;
		arrs = (T[]) new Object[this.size];
	}

	/**
	 * 队列是否满
	 * 
	 * @return
	 */
	public boolean isFull() {
		return (rear - front + 1) % size == 0;
	}
	
	/**
	 * 队列是否为空
	 * 
	 * @return
	 */
	public boolean isEmpty() {
		return rear == front;
	}

	/**
	 * 往队列中加入数据
	 * 
	 * @param data
	 */
	public void add(T data) {
		if (isFull()) {
			throw new RuntimeException("队列已满");
		}
		
		arrs[rear] = data;
		rear = (rear + 1) % size;
	}

	/**
	 * 从队列中获取数据
	 * 
	 * @return
	 */
	public T get() {
		if (isEmpty()) {
			throw new RuntimeException("队列为空");
		}
		
		int tmp = front;
		front = (front + 1) % size;
		
		return arrs[tmp];
	}
}

Golang版本:

package queue

import "errors"

// ArrayQueue 基于切片实现队列
type ArrayQueue struct {
	// 指向队头的下标
	front int64

	// 指向队尾的下标下一个下标
	rear int64

	// 队列的最大容量
	size int64

	// 存放数据的数组容器
	arrs []interface{}
}

// NewArrayQueue 获取指定大小的队列
func NewArrayQueue(size int64) *ArrayQueue {
	return &ArrayQueue{
		size: size + 1,
		arrs: make([]interface{}, size+1),
	}
}

// ISFull 队列是否满
func (q *ArrayQueue) ISFull() bool {
	return (q.rear-q.front+1)%q.size == 0
}

// ISEmpty 队列是否为空
func (q *ArrayQueue) ISEmpty() bool {
	return q.rear == q.front
}

// Add 往队列中加入数据
func (q *ArrayQueue) Add(data interface{}) error {
	if q.ISFull() {
		return errors.New("queue is full")
	}

	q.arrs[q.rear] = data
	q.rear = (q.rear + 1) % q.size

	return nil
}

// Get 从队列中获取数据
func (q *ArrayQueue) Get() (interface{}, error) {
	if q.ISEmpty() {
		return nil, errors.New("queue is empty")
	}

	tmp := q.front
	q.front = (q.front + 1) % q.size

	return q.arrs[tmp], nil
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值