Java中的栈和队列以及转换

一.栈(Stack)

是一种后进先出 (LIFO, Last In First Out) 的数据结构。只允许在一端进行元素的删除或插入,也就是说,最后一个加入栈的元素最先被移除。这一端被称为栈顶(Top),另一端被称为栈底(Bottom)。

栈的基本操作包括:

压栈 (Push):将元素添加到栈的顶部。

弹栈 (Pop):移除并返回栈顶的元素。

查看栈顶元素 (Peek):返回栈顶的元素,但不移除它。

判断栈是否为空(IsEmpty):检查栈中是否有元素。

栈的实现通常使用数组或链表。数组实现的栈有固定大小,而链表实现的栈可以动态调整大小。

栈的Java数组实现

 public class MyStackArr {
     private int maxSize;//栈大小
     private int[] stackArray;//栈
     private int top;//栈顶
     //栈的初始化 自定义栈的大小
     public MyStackArr(int size) {
         maxSize = size;
         stackArray = new int[maxSize];
         top = -1;
     }
    //压栈操作
     public void push(int value) {
         if (top == maxSize - 1) {
             throw new RuntimeException("栈已满!");
         }
         stackArray[++top] = value;
     }
   //弹栈操作
     public int pop() {
         if (top == -1) {
             throw new RuntimeException("栈为空!");
         }
         int value = stackArray[top];
         stackArray[top--] = 0; // 将弹出的元素位置设置为0
         return value;
     }
   //查看栈顶元素操作
     public int peek() {
         if (top == -1) {
             throw new RuntimeException("栈为空!");
         }
         return stackArray[top];
     }
 //判断栈是否为空操作
     public boolean isEmpty() {
         return (top == -1);
     }
 //判断栈是否已满操作
     public boolean isFull() {
         return (top == maxSize - 1);
     }
 }
 ​

栈的Java链表实现:

 private ListNode top;
 ​
     public LinkedListStack() {
         this.top = null;
     }
 ​
     public void push(int value) {
         ListNode newNode = new ListNode(value);
         newNode.next = top;
         top = newNode;
     }
 ​
     public int pop() {
         if (top == null) {
             throw new RuntimeException("栈为空!");
         }
         int value = top.value;
         top = top.next;
         return value;
     }
 ​
     public int peek() {
         if (top == null) {
             throw new RuntimeException("栈为空!");
         }
         return top.value;
     }
 ​
     public boolean isEmpty() {
         return top == null;
     }

二.队列(Queue)

队列是一种先进先出(FIFO, First In First Out)的数据结构。双端操作,它允许在一端插入元素(称为队尾),在另一端删除元素(称为队头)。

队列的基本操作

初始化队列:创建一个空队列。

入队(Enqueue):将元素添加到队尾。

出队(Dequeue):从队头移除元素。

读队头元素(GetFront):获取队头元素但不删除。

判队空(QueueEmpty):判断队列是否为空

队列的实现通常使用数组、链表或循环数组。循环数组可以有效地利用空间,避免数组实现中的空间浪费问题。

队列的Java数组实现:


public class MyQueueArr {
    private int maxSize; // 队列的最大容量
    private int[] queueArray; // 用于存储队列元素的数组
    private int front; // 队头指针
    private int rear; // 队尾指针
    private int nItems; // 队列中的元素数量

    // 构造函数,初始化队列
    public MyQueueArr(int size) {
        maxSize = size; // 设置队列的最大容量
        queueArray = new int[maxSize]; // 创建存储队列元素的数组
        front = 0; // 初始化队头指针
        rear = -1; // 初始化队尾指针
        nItems = 0; // 初始化队列中的元素数量
    }

    // 入队操作,将元素添加到队尾
    public void enqueue(int value) {
        if (rear == maxSize - 1) { // 如果队尾指针到达数组末尾
            rear = -1; // 将队尾指针重置为-1(循环队列)
        }
        queueArray[++rear] = value; // 将元素添加到队尾,并移动队尾指针
        nItems++;
    }

    // 出队操作,从队头移除元素
    public int dequeue() {
        if (nItems == 0) { 
            throw new RuntimeException("队列为空!"); 
        }
        int temp = queueArray[front++]; 
        if (front == maxSize) { 
            front = 0; // 将队头指针重置为0(循环队列)
        }
        nItems--; 
        return temp; 
    }

    // 获取队头元素
    public int peekFront() {
        if (nItems == 0) {
            throw new RuntimeException("队列为空!");
        }
        return queueArray[front]; // 返回队头元素
    }

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

    // 判断队列是否已满
    public boolean isFull() {
        return (nItems == maxSize);
    }
}

队列的Java链表实现

class ListNode {
    int value;
    ListNode next;

    ListNode(int value) {
        this.value = value;
        this.next = null;
    }
}

public class MyQueueLink {
    private ListNode front;
    private ListNode rear;

    public MyQueueLink() {
        this.front = null;
        this.rear = null;
    }

    public void enqueue(int value) {
        ListNode newNode = new ListNode(value);
        if (rear == null) {
            front = rear = newNode;
        } else {
            rear.next = newNode;
            rear = newNode;
        }
    }

    public int dequeue() {
        if (front == null) {
            throw new RuntimeException("队列为空!");
        }
        int value = front.value;
        front = front.next;
        if (front == null) {
            rear = null;
        }
        return value;
    }

    public int peek() {
        if (front == null) {
            throw new RuntimeException("队列为空!");
        }
        return front.value;
    }

    public boolean isEmpty() {
        return front == null;
    }
}

三.栈和队列的转换

1.栈实现队列

使用两个栈来实现一个队列。一个栈用于存储新元素,另一个栈用于反转元素顺序以实现队列的先进先出特性。

思路

  1. 入队操作:将元素压入第一个栈。
  2. 出队操作:如果第二个栈为空,则将第一个栈中的所有元素弹出并压入第二个栈,然后从第二个栈弹出元素。

java代码实现:

public class MyQueueUsingMyStack {
    private MyStack stackPush;
    private MyStack stackPop;

    public MyQueueUsingMyStack(int size) {
        stackPush = new MyStack(size);
        stackPop = new MyStack(size);
    }

    public void enqueue(int value) {
        stackPush.push(value);
    }

    public int dequeue() {
        if (stackPop.isEmpty()) {
            while (!stackPush.isEmpty()) {
                stackPop.push(stackPush.pop());
            }
        }
        if (stackPop.isEmpty()) {
            throw new RuntimeException("队列为空!");
        }
        return stackPop.pop();
    }

    public boolean isEmpty() {
        return stackPush.isEmpty() && stackPop.isEmpty();
    }
}

2.队列实现栈

我们将使用两个你自己设计的队列来实现一个栈。一个队列用于存储新元素,另一个队列用于辅助反转元素顺序以实现栈的后进先出特性。

思路

  1. 压栈操作:将元素添加到第一个队列。
  2. 弹栈操作:将第一个队列中的前n-1个元素移到第二个队列,最后一个元素即为栈顶元素,将其弹出。然后交换两个队列的角色。

java代码实现

public class MyStackUsingMyQueue {
    private MyQueue queue;
    private MyQueue helpQueue;

    public MyStackUsingMyQueue(int size) {
        queue = new MyQueue(size);
        helpQueue = new MyQueue(size);
    }

    public void push(int value) {
        queue.enqueue(value);
    }

    public int pop() {
        if (queue.isEmpty()) {
            throw new RuntimeException("栈为空!");
        }
        while (queue.size() > 1) {
            helpQueue.enqueue(queue.dequeue());
        }
        int res = queue.dequeue();
        MyQueue temp = queue;
        queue = helpQueue;
        helpQueue = temp;
        return res;
    }

    public int peek() {
        if (queue.isEmpty()) {
            throw new RuntimeException("栈为空!");
        }
        while (queue.size() > 1) {
            helpQueue.enqueue(queue.dequeue());
        }
        int res = queue.dequeue();
        helpQueue.enqueue(res);
        MyQueue temp = queue;
        queue = helpQueue;
        helpQueue = temp;
        return res;
    }

    public boolean isEmpty() {
        return queue.isEmpty();
    }
}

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值