前言
总体来说,栈和队列也是线性结构的一种,至于什么是栈,什么是队列,这里不会介绍,因为这玩意太基础。这里就不总结了,只是说一下,这里的栈和队列的底层实现其实有数组和链表的两种实现方式。
栈的基本操作
这里采用链表的实现方式,一个链表节点作为栈顶,一个链表节点作为栈底
基本数据结构如下所示:
/**
* autor:liman
* createtime:2020/2/5
* comment: 栈,自己的栈操作,底层采用链表的数据结构
*/
public class MyStack {
private ListNode stackTop;
private ListNode stackBottom;
public MyStack(ListNode stackTop,ListNode stackBottom){
this.stackTop = stackTop;
this.stackBottom = stackBottom;
}
}
相关的入栈,出栈等操作
/**
* 入栈操作
* @param stack
* @param value
* 这个就好比在top头插入一个节点
*/
public static void pushStack(MyStack stack,int value){
ListNode node = new ListNode(value);
node.next = stack.stackTop;
stack.stackTop=node;
}
/**
* 遍历操作
* @param stack
* 遍历,利用stackTop进行走链的操作
*/
public static void traverse(MyStack stack){
ListNode stackTop = stack.stackTop;
while(stackTop!=stack.stackBottom){
System.out.print(stackTop.value +" ");
stackTop = stackTop.next;
}
System.out.println();
}
/**
* 栈的判空操作
* @param stack
* @return
*
*/
public static boolean isEmpty(MyStack stack){
if(stack.stackTop == stack.stackBottom){
return true;
}else{
return false;
}
}
/**
* 出栈
* @param stack
* 在栈非空的情况下,相当于删除头节点。
*/
public static void popStack(MyStack stack){
if(!isEmpty(stack)){
ListNode stackTop = stack.stackTop;
stack.stackTop = stackTop.next;
System.out.println(stackTop.value);
}
}
/**
* 清空栈中的元素
* @param stack
* 这个够简单了,其余的节点会被JVM自动回收
*/
public static void clearStack(MyStack stack){
stack.stackTop = null;
stack.stackBottom = stack.stackTop;
}
队列的基本操作
栈的基本操作底层是基于链表实现的,这里的队列采用数组的方式实现。至于这个循环队列的底层图解,这个还是百度吧
public class MyQueue {
public int[] arrays;
public int front; //指向的是第一个有效的元素
public int rear; //指向的是最后一个有效元素的下一个元素
public MyQueue(int[] arrays, int front, int rear) {
this.arrays = arrays;
this.front = front;
this.rear = rear;
}
}
这里需要注意一下rear的指向,这个指向的是数组中最右一个有效元素的下一个元素,这个存储空间是个无效的元素
/**
* 判断队列是否是满的
* (queue.rear+1)%queue.length == queue.front,则表示队列已满
* @param queue
* @return
*/
public static boolean isFull(MyQueue queue) {
if ((queue.rear + 1) % queue.arrays.length == queue.front) {
return true;
} else {
return false;
}
}
/**
* 判断队列是否是空
* queue.rear == queue.front则表示队列为空,这是最初始的状态
* @param queue
* @return
*/
public static boolean isEmpty(MyQueue queue) {
if (queue.rear == queue.front) {
return true;
} else {
return false;
}
}
/**
* 入队操作
* 即操作队尾,将元素放到rear所指向的空间,然后rear前移 【(rear+1)%queue.length】
* @param queue
* @param value
*/
public static void enQueue(MyQueue queue, int value) {
if (!isFull(queue)) {
queue.arrays[queue.rear] = value;
queue.rear = (queue.rear + 1) % queue.arrays.length;
}
}
/**
* 遍历操作
*
* @param queue
*/
public static void traverse(MyQueue queue) {
int i = queue.front;
while (i != queue.rear) {
System.out.println(queue.arrays[i]);
i = (i + 1) % queue.arrays.length;
}
}
/**
* 出队操作
* 操作对头指针,front。之后front前移【(front+1)%queue.length】
*/
public static void outQueue(MyQueue queue) {
if (!isEmpty(queue)) {
int value = queue.arrays[queue.front];
System.out.println(value);
queue.front = (queue.front + 1) % queue.arrays.length;
}
}
利用两个栈实现一个队列
思路:一个栈承接如对列的元素,在出队列之前,将第一个栈中的元素出栈,然后将元素入栈到第二个栈中即可,出队列即为从第二个栈中弹出元素。这里用Java底层的集合Stack来完成这个需求
public class DoubleStack2Queue {
public Stack<Integer> stackPush; //用于入队列的栈
public Stack<Integer> stackPop; //用于出队列的栈
public DoubleStack2Queue(Stack<Integer> stackPush, Stack<Integer> stackPop) {
this.stackPush = stackPush;
this.stackPop = stackPop;
}
/**
* 入队列。
*/
public void add(int value){
stackPush.push(value);
}
/**
* 出队列的操作
* @return
*/
public int poll(){
if(stackPop.isEmpty() && stackPush.isEmpty()){//队列为空
throw new RuntimeException("队列为空");
}else if(stackPop.isEmpty()){
while(!stackPush.isEmpty()){//一股脑的直接将入队列的栈里面的所有元素放到出队列的栈中。
stackPop.push(stackPush.pop());
}
}
return stackPop.pop();
}
/**
* 只是单纯的读取栈顶的元素
* @return
*/
public int peek(){
if(stackPop.isEmpty() && stackPush.isEmpty()){//队列为空
throw new RuntimeException("队列为空");
}else if(stackPop.isEmpty()){
while(!stackPush.isEmpty()){
stackPop.push(stackPush.pop());
}
}
return stackPop.peek();
}
}
总结
是不是太easy了,都不想总结了。