java数据结构之队列的实现

数据结构中队列的相关概念

队列的介绍
队列是一个有序列表,可以用数组或是链表的方式来实现
特性:遵循先进先出(first in first out)的原则,即FIFO原则,
操作:只允许在尾部插入、在头部删除的数据结构
说人话就是:类似我们现实生活中排队的队列,先排队的人就越早能得到自己想要的,
在这里我们分别用数组和链表来实现队列。

数组在内存中本来就是有先后顺序的,这里刚好可以用表示队列之间的有序性
关键词:容量(capacity)、长度(size)、队列的队头(front)、队列的队尾(rear)
二话不说,向上代码。

1、数组实现队列

public class ArrayQueue <T> {
    
    
	//    默认初始时数组的容量,
    private static final int DEFAULT_CAPACITY = 10;
    // 这里创建一个空的数组
    private static final Object[] EMPTY_ELEMENTDATA = {
    
    };
    // 定义数组的最大容量,如果当实际容量操作最大容量的时候,可以进行扩容,也可以直接报错
    private int capacity;
    // 定义队列的长度,即实际个数
    private int size;
    // 定义头指针
    private int front;
    // 定义尾指针,在后续存入数据的时候,指向的队列尾部的后一个空的位置
    private int rear;
    // 提供一个无参构造函数
    private Object[] arrary;
    
    public ArrayQueue (){
    
    
    	//这里设置默认的容量是10个,相当于new Object[10];
    	this.arrary = new Object[DEFAULT_CAPACITY];
    	this.capacity = DEFAULT_CAPACITY;
    	//初始化的队列的size 是 0
    	this.size = 0;
    	this.front = 0;
    	this.rear = 0;
	}
	
	// 在这里创建一个可以让自定最大容量的队列
	public ArrayQueue (int capacity ){
    
    
    	//这里设置默认的容量是10个,相当于new Object[10];
    	this.arrary = new Object[capacity ];
    	this.capacity = capacity ;
    	//初始化的队列的size 是 0
    	this.size = 0;
    	this.front = 0;
    	this.rear = 0;
	}
	
	// 判断是否为空
	public boolean isEmpty(){
    
    
		if(this.rear == this.front){
    
    
			return true;
		}
		return false;
	}
	
	// 判断是否已经满了
	public boolean isFull(){
    
    
		if((this.rear -this.front) == this.capacity ){
    
    
			return true;
		}
		return false;
	}
	
	//向队列中添加数据,注意这里只能从队尾加入
	public void add(T t){
    
    
		// 在每次加入数据的时候都必须检查一下当前队列的队尾是否已经大于最大容量了,
		if(this.rear >this.capacity ){
    
    
			// 这里可以进行扩容、或报错
			throw  new RuntimeException("队列已满");
		}
		// 进行添加操作
		this.array[rear] = t;
		rear+=1;
		size+=1;
	}
	
	//将队列头部的元素删除,这里只能删除头部的
	public Object remove(){
    
    
		//每次删除的数据的时候判断队列是否为空
		if(this.isEmpty()){
    
    
			throw new RuntimeException("队列为空,没有可删除的数据了");
		}
		Object obj = this.arrary[this.front];
		this.front += 1;
		this.size -= 1;
		return obj ;
	}
	
}

2、循环队列的实现

public class CircleQueue <T> {
    
    
	//    默认初始时数组的容量,
    private static final int DEFAULT_CAPACITY = 10;
    // 这里创建一个空的数组
    private static final Object[] EMPTY_ELEMENTDATA = {
    
    };
    // 定义数组的最大容量,如果当实际容量操作最大容量的时候,可以进行扩容,也可以直接报错
    private int capacity;
    // 定义队列的长度,即实际个数
    private int size;
    // 定义头指针
    private int front;
    // 定义尾指针,在后续存入数据的时候,指向的队列尾部的后一个空的位置
    private int rear;
    // 提供一个无参构造函数
    private Object[] arrary;
    
	public CircleQueue(){
    
    
	//这里设置默认的容量是10个,相当于new Object[10];
    	this.arrary = new Object[DEFAULT_CAPACITY];
    	this.capacity = DEFAULT_CAPACITY;
    	//初始化的队列的size 是 0
    	this.size = 0;
    	this.front = 0;
    	this.rear = 0;
	}
	
	// 指定创建队列时的容量
	public CircleQueue(int capacity){
    
    
	this.arrary = new Object[capacity];
    	this.capacity = capacity;
    	//初始化的队列的size 是 0
    	this.size = 0;
    	this.front = 0;
    	this.rear = 0;
	}
	
	// 判断队列是否为空
	public boolean isEmpty(){
    
    
		return front == rear;
	}
	
	// 判断队列是否已经满了,因为这里是循环队列使用的
	public boolean isFull(){
    
    
		// 再循环队列中,只有满足这种情况的,队列才满的
		return (rear + 1) % maxSize == front;
	}
	
	// 获取队列的长度
	public int size(){
    
    
		// 因为这是在循环队列之中,会出现rear 比front 小的情况,所以长度实际的计算是下面的公式
		return (rear + capacity - front) % capacity ;
	}
	
	//从队尾入队列
	public void enQueue(T t){
    
    
		// 每次插入数据的时候都必须判断一下队列是否已经满了
		if(isFull()){
    
    
			// 队列已满的情况下,可以对队列进行扩容或者报错,这里直接抛出一个异常
			throw new RuntimeException("队列已满,无法插入数据!");
		}
		this.arrary[rear] = t;
		// 在循环队列中rear 不再是简单的+1,有一种情况是rear 已经到capacity - 1 的位置
		rear = (rear+1) % capacity ;
	}
	
	// 手机设队头元素
	public Object delQueue(){
    
    
	//每次在删除钱判断队列 是否为空
		if(isEmpty()){
    
    
			throw new RuntimeException("队列已满,无法插入数据!");
		}
		Object obj = this.arrary.[front];
		front = (front + 1) % capacity ;
		return obj ;
	}
	
	// 清空队列的操作
	public void clear(){
    
    
		this.arrary = EMPTY_ELEMENTDATA;
	}
}
	

使用链表的方式实现队列
在学习链表前,我们先学习一下结点(Node),在结点中有一个存放数据的域称为数据域,用于存放下一个元结点位置的称为指针

public class Node<T> {
    
    
	// 用于存放数据的域
	privte T data;
	//用于指向下一个结点的指针
	priate Node next;
}
public class LinkQueue<T>{
    
    
	private Node head;
	public LinkQueue(){
    
    
		// 在这里头指针我们是不存放任何数据的
		head.data = null;
		head.next = null;
	}
	
	// 如果队列的头指针的next指针为空,即队列中没有元素
	public boolean isEmpty(){
    
    
		return head.next == null;
	}
	
	public void enQueue(T t){
    
    
		// 判断传入的数据是否为空
		if(t == null){
    
    
			throw  new RuntimeException("传入的数据为空,无法插入!");
		}
		Node temp = head;
		//找到队尾,即temp.next为空的元素
		while(temp.next != null ){
    
    
			temp = temp.next;
		}
		Node insertNode = new Node();
		insertNode.data = t;
		// 这里相当于 insertNode.next = null;
		insertNode.next = temp.next;
		temp.next = insertNode ;
	}
	
	// 从队列中删除队头元素
	public Object delQueue(){
    
    
		// 判断 队列是否为空
		if(isEmpty()){
    
    
			throw new RuntimeException("队列为空,无法删除!");
		}
		Node delNode = head.next;
		// 将头指针的next 指向删除节点的下一个节点
		head.next = delNode.next;
		return delNode.data;
	}
	
	// 获取队列的长度
	public int size(){
    
    
		Node temp = head;
		int size = 0 ;
		while(temp.next != null){
    
    
			size ++
		}
		return size;
	}
	
	// 获取队头的数据,但不出队列,即查看
	public Object getHead(){
    
    
		Node firstNode = head.next;
		return firstNode.data;
	} 
	
}

猜你喜欢

转载自blog.csdn.net/Hicodden/article/details/105911047