数据结构--栈和队列

一、栈(Stack)

栈是一种先进后出的数据结构。其只允许在固定的一端进行插入和删除元素操作

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶

出栈:栈的删除操作叫做出栈。出数据在栈顶
 

1.栈的使用

 栈的模拟实现:

使用数组实现

public class MyStack implements IStack{
    private int[] elem;//定义一个数组
    private int usedSize;//数组的有效数据个数
    private static final int DEFAULT_SIZE = 10;//数组的默认大小
    public MyStack(){
        elem = new int[DEFAULT_SIZE];
    }
}
1.入栈 
public void push(int x) {
        if(full()){
            //满了就扩容
            elem = Arrays.copyOf(elem,elem.length*2);
        }
        elem[usedSize]=x;
        usedSize++;
    }
2.出栈
public int pop() {
        if(isEmpty()){
            //栈若为空,这里抛出异常!!!
            throw new ElemNullException("栈为空!");
        }
        int e = elem[usedSize-1];
        usedSize--;
        //若是引用类型,应该置空
        //elem[usedSize]=null;
        return e;
    }
3.查看栈顶元素
public int peek() {
        if(isEmpty()){
            throw new ElemNullException("栈为空!");
        }
        return elem[usedSize-1];
    }
4.栈里有多少元素
public int size() {
        return usedSize;
    }
5.栈是否为空
public boolean isEmpty() {
        if(usedSize==0){
            return true;
        }
        return false;
    }
栈的应用场景:

逆波兰表达式求值

 逆波兰式是一种将待计算量写在前, 把运算符写在后(通常是两数之后)的计算式。

代码实现:

public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        for(String x : tokens){
            if(!isOperate(x)){
                //不是操作符,入栈,要转成int类型
                stack.push(Integer.parseInt(x));
            }else{
                int nums2 = stack.pop();//右操作数
                int nums1 = stack.pop();//左操作数
                switch(x){
                    case "+":
                        stack.push(nums1+nums2);
                        break;
                    case "-":
                        stack.push(nums1-nums2);
                        break;
                    case "*":
                        stack.push(nums1*nums2);
                        break;
                    case "/":
                        stack.push(nums1/nums2);
                        break;
                }
            }
        }
        return stack.pop();
    }
    private boolean isOperate(String s){
        if(s.equals("+")||s.equals("-")||s.equals("*")||s.equals("/")){
            return true;
        }
        return false;
    }

二、队列

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进

先出FIFO(FirstIn First Out)

入队列:进行插入操作的一端称为队尾(Tail/Rear)

出队列:进行删除操作的一端称为队头。


 

 双向链表实现队列
static class ListNode{
        public int val;
        public ListNode next;
        public ListNode prev;

        public ListNode(int val) {
            this.val = val;
        }
    }
    public ListNode head;
    public ListNode last;
    public int usedSize;
入队
public boolean offer(int val){
        ListNode node = new ListNode(val);
        if(head==null){
            head=node;
            last=node;
        }else{
            last.next = node;
            node.prev = last;
            last = node;
        }
        usedSize++;
        return true;
    }
出队
public int poll(){
        if(head == null){
            return -1;
        }
        int val = head.val;
        if(head.next==null){
            head=null;
            last=null;
        }else{
            head=head.next;
            head.prev=null;
        }
        usedSize--;
        return val;

    }
查看队头元素
public int peek(){
        if(head==null){
            return -1;
        }
        return head.val;
    }
队列是否为空
public boolean empty(){
        return head == null;
    }
队列长度
public int size(){
        return usedSize;
    }

循环队列

设计循环队列主要就是注意 front 和 rear 的位置,它们不能超过数组长度。

如何区分空与满???

这里浪费一个空间来演示:

先创建循环队列:

class MyCircularQueue {
    public int[] elem;
    public MyCircularQueue(int k) {
        elem = new int[k+1];
    }
    public int front;//队头
    public int rear;//队尾
}
入队

防止 rear 越界,往后移的同时应该 % 数组长度!!!

不能直接写 rear++ !!

public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }
        elem[rear]=value;
        rear = (rear+1) % elem.length;//rear不能++
        return true;
    }
出队

队头位置要后移,同样要 % 数组长度!!

public boolean deQueue() {
        if(isEmpty()){
            return false;
        }
        front = (front+1)%elem.length;
        return true;
    }
查看队头元素
public int Front() {
        if(isEmpty()){
            return -1;
        }
        return elem[front];
    }
获取队尾元素

rear 不能直接减,如果恰好在0位置,rear-1 变成负数了,所以这里应该判断:

如果在0位置,直接返回数组长度 -1,否则就是 rear-1;

public int Rear() {
        if(isEmpty()){
            return -1;
        }
        int index = (rear==0) ? elem.length-1 : rear-1;//当rear在0位置处时不能-1
        return elem[index];
    }
 队空
public boolean isEmpty() {
        return front==rear;
    }
队满

public boolean isFull() {
        return (rear+1) % elem.length == front;
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值