基本队列,双端队列,循环队列及循环双端队列的简单实现

队列是一种特殊的线性表,只能在头尾两端进行操作,遵循先进先出的原则。下面是一些队列接口的简单实现。

双向链表实现基本队列

package com.ldg.queue;

import com.ldg.doubles.LinkedList;

/***
 * 队列:首部执行出队 尾部执行入队 只在首尾进行操作 所以底层用双向链表来实现 时间复杂度很小
 * 
 * @author Administrator
 *
 */
public class Queue<T> {

	// 双向链表实现
	private LinkedList<T> linkedList = new LinkedList<>();

	// 入队
	public void enQueue(T element) {
		linkedList.add(element);
	}

	// 出队
	public T deQueue() {
		return linkedList.remove(0);
	}

	// 判断是队列否为空
	public Boolean isEmpty() {
		return size() == 0;
	}

	// 队列大小
	public int size() {
		return linkedList.getSize();
	}

	// 获取首部元素
	public T front() {
		return linkedList.get(0);
	}

	// 清空队列
	public void clear() {
		linkedList.clear();
	}

	@Override
	public String toString() {

		StringBuilder stringBuilder = new StringBuilder();

		stringBuilder.append("Size:" + size() + " Queue[");
		for (int i = 0; i < size(); i++) {
			if (i != 0) {
				stringBuilder.append(",");
			}

			stringBuilder.append(linkedList.get(i));
		}
		stringBuilder.append("]");

		return stringBuilder.toString();

	}
}

栈实现基本队列

package;

import java.util.Stack;

//声明两个stack
public class _232_用栈实现队列 {

	// 一个用来push
	Stack<Integer> inStack = new Stack<Integer>();
	// 一个用来peek pop
	Stack<Integer> outStack = new Stack<Integer>();

	// 入队
	public void push(int x) {

		inStack.push(x);

	}

	// 出队
	public int pop() {
		// 判断outStack是不是为空
		if (outStack.isEmpty()) {
			// 将inStack的元素放入outStack中
			while (!inStack.isEmpty()) {
				outStack.push(inStack.pop());
			}
		}

		return outStack.pop();

	}

	// 查看首部元素
	public int peek() {

		if (outStack.isEmpty()) {
			// 将inStack的元素放入outStack中
			while (!inStack.isEmpty()) {
				outStack.push(inStack.pop());
			}
		}

		return outStack.peek();
	}

	//判断队列是否为空
	public boolean empty() {

		return inStack.isEmpty() && outStack.isEmpty();

	}
   
	
}

**双端队列 **
双端队列指的是在首部和尾部都可以进行出队和入队的操作。

package com.ldg.deque;

import com.ldg.doubles.LinkedList;

/**
 * 双端队列:在首尾都可以执行出队和入队 双向链表实现
 * 
 * @author Administrator
 *
 * @param <T>
 */
public class Deque<T> {

	// 双向链表
	private LinkedList<T> linkedList = new LinkedList<>();

	// 队列大小
	public int size() {

		return linkedList.getSize();
	}

	// 从尾部入队
	public void enQueueRear(T element) {

		linkedList.add(element);
	}

	// 从首部入队
	public void enQueueFront(T element) {

		linkedList.add(0, element);

	}

	// 从尾部出队
	public T deQueueRear() {

		return linkedList.remove(size() - 1);

	}

	// 从首部出队
	public T deQueueFront() {

		return linkedList.remove(0);
	}

	public boolean isEmpty() {

		return size() == 0;
	}

	// 获取首部元素
	public T front() {

		return linkedList.get(0);

	}

	// 获取尾部元素
	public T rear() {

		return linkedList.get(size() - 1);
	}

	// 清空队列
	public void clear() {
		linkedList.clear();

	}

	@Override
	public String toString() {

		StringBuilder stringBuilder = new StringBuilder();

		stringBuilder.append("Size:" + size() + " DeQueue[");
		for (int i = 0; i < size(); i++) {
			if (i != 0) {
				stringBuilder.append(",");
			}

			stringBuilder.append(linkedList.get(i));
		}
		stringBuilder.append("]");

		return stringBuilder.toString();

	}
}

双端队列的测试在这里插入图片描述

循环队列
循环队列:底层用优化后的动态数组实现 所以有循环的感觉
ps:就是在首部出队时不需要将第二个元素到尾部元素一个个往前移动
ps:在尾部入队时不一定要一味往后加 ,可以利用数组前面的空间
这样方法实现的复杂度也是O(1)

package com.ldg.circleQueue;

//循环队列:底层用优化后的动态数组实现 所以有循环的感觉
//         ps:就是在首部出队时不需要将第二个元素到尾部元素一个个往前移动
//         ps:在尾部入队时不一定要一味往后加 ,可以利用数组前面的空间
//这样方法实现的复杂度也是O(1)

@SuppressWarnings("unchecked")
public class CircleQueue<T> {

	// 首部序号
	private int frist;
	private int size;
	// 数组初始长度
	private final static int length = 10;

	// 声明一个泛型数组
	@SuppressWarnings("unused")
	private T[] elements;

	// 初始化数组
	public CircleQueue() {

		elements = (T[]) new Object[length];
	}

	// 入队 (size+frist)%elements.length取模运算可以利用到前面的空间
	public void enQueue(T element) {
		isAddCapcity();
		// elements[(size + frist) % elements.length] = element;
		elements[index(size)] = element;
		size++;
	}

	// 出队 (frist + 1) % elements.length 找到第首部下一个元素
	public T deQueue() {

		T old = elements[index(0)];
		elements[index(0)] = null;
		frist = index(1);
		size--;
		return old;

	}

	// 判断队列是否为空
	public Boolean isEmpty() {

		return size == 0;
	}

	// 获取队列元素个数
	public int size() {

		return size;
	}

	// 查看首部元素的值
	public T front() {

		return elements[frist];
	}

	// 清空队列
	public void clear() {

		for (int i = 0; i < size; i++) {
			elements[i] = null;

		}
		size = 0;
		frist = 0;
	}
	


	// 是将整个数组打印
	@Override
	public String toString() {

		StringBuilder stringBuilder = new StringBuilder();

		stringBuilder.append("Size:" + elements.length + " Frist:" + frist + " CircleQueue[");
		for (int i = 0; i < elements.length; i++) {
			if (i != 0) {
				stringBuilder.append(",");
			}

			stringBuilder.append(elements[i]);
		}
		stringBuilder.append("]");

		return stringBuilder.toString();

	}

	// 判断是否扩容
	private void isAddCapcity() {
		if ((size + 1) > elements.length) {
			int newCapcity = elements.length << 1;
			T[] newElemenTs = (T[]) new Object[newCapcity];
			for (int i = 0; i < elements.length; i++) {
				// newElemenTs[i] = elements[(frist + i) % elements.length];
				newElemenTs[i] = elements[index(i)];
			}
			frist = 0;
			elements = newElemenTs;
		}
	}

	// 索引映射:将逻辑索引映射成真实索引 并返回
	private int index(int index) {
		// 取模运算可以优化一下
		// return (frist+index)%elements.length;
		// 因为 0<=length<2elements.length
		int length = frist + index;
		return length >= elements.length ? length - elements.length : length;
	}

}

循环队列的测试
在这里插入图片描述
循环双端队列
循环双端队列:底层用优化后的动态数组实现 ,可以在首部和尾部进行入队,出队的操作。

package com.ldg.circleDeque;

/**
 * 循环双端队列:底层用优化后的动态数组实现 ,可以在首部和尾部进行入队,出队的操作。
 * 
 * @author Administrator
 *
 */
@SuppressWarnings("unchecked")
public class CircleDeque<T> {

	// 首部序号
	private int frist;
	private int size;
	// 数组初始长度
	private final static int length = 10;
	// 声明一个泛型数组
	@SuppressWarnings("unused")
	private T[] elements;
    // 初始化数组
	public CircleDeque() {

		elements = (T[]) new Object[length];
	}
    //获取队列长度
	public int size() {

		return size;
	}
    //尾部入队
	public void enQueueRear(T element) {

		isAddCapcity();
		// elements[(size + frist) % elements.length] = element;
		elements[index(size)] = element;
		size++;

	}

	//首部入队
	public void enQueueFront(T element) {

		isAddCapcity();
		// 首部元素序号为0参考
		frist = index(-1);
		elements[frist] = element;
		size++;

	}
    //尾部出队
	public T deQueueRear() {

		T old = elements[index(size - 1)];
		elements[index(size - 1)] = null;
		size--;

		return old;

	}
    //首部出队
	public T deQueueFront() {

		T old = elements[index(0)];
		elements[index(0)] = null;
		frist = index(1);
		size--;
		return old;
	}
    //判断是队列是否为空
	public boolean isEmpty() {

		return size() == 0;
	}
    //查看首部元素
	public T front() {

		return elements[index(0)];
	}
    //查看尾部元素
	public T rear() {

		return elements[index(size - 1)];
	}
	// 清空队列
		public void clear() {

			for (int i = 0; i < size; i++) {
				elements[i] = null;

			}
			size = 0;
			frist = 0;
		}
	@Override
	public String toString() {

		StringBuilder stringBuilder = new StringBuilder();

		stringBuilder.append("Size:" + size() + " frist" + frist + " CircleDeQueue[");
		for (int i = 0; i < elements.length; i++) {
			if (i != 0) {
				stringBuilder.append(",");
			}

			stringBuilder.append(elements[i]);
		}
		stringBuilder.append("]");

		return stringBuilder.toString();

	}

	// 判断是否扩容
	private void isAddCapcity() {
		if ((size + 1) > elements.length) {
			int newCapcity = elements.length << 1;
			T[] newElemenTs = (T[]) new Object[newCapcity];
			for (int i = 0; i < elements.length; i++) {
				// newElemenTs[i] = elements[(frist + i) % elements.length];
				newElemenTs[i] = elements[index(i)];
			}
			frist = 0;
			elements = newElemenTs;
		}
	}

	// 索引映射:将逻辑索引映射成真实索引 并返回
	private int index(int index) {

		if (index < 0) {
			// 当在首部入队时要考虑的
			return frist > 0 ? frist + index : index + elements.length;
		} else {
			// 其他情况
			// 取模运算可以优化一下
			// return (frist+index)%elements.length;
			// 因为 0<=length<2elements.length
			int length = frist + index;
			return length >= elements.length ? length - elements.length : length;
		}
	}
}

循环双端队列测试
在这里插入图片描述就这样吧。

发布了23 篇原创文章 · 获赞 17 · 访问量 1285

猜你喜欢

转载自blog.csdn.net/qq_41587409/article/details/105340010