数据结构——栈和队列

作者~小明学编程 

文章专栏Java数据结构

格言目之所及皆为回忆,心之所想皆为过往
在这里插入图片描述

目录

概念

 实现

队列

概念

 实现

循环队列

数组下标循环技巧

判断队列的空与满

代码

双端队列(Deque)

概念

Java中的栈和队列

​编辑

概念

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

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

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

 

 实现

1. 利用顺序表实现,即使用尾插 + 尾删的方式实现。
2. 利用链表实现,则头尾皆可(一般用双向链表)。

这里介绍一下用顺序表实现的方式。

public class MyStack {

    private int[] elem;
    private int usedSize=0;

    public MyStack() {
        this.elem = new int[5];
    }

    public void push(int val) {
        if (isFull()) {
            //扩容
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }
        this.elem[usedSize] = val;
        this.usedSize++;
    }

    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空!");
        }
        usedSize--;
        return this.elem[usedSize];
    }

    public int peek() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空!");
        }
        return this.elem[usedSize-1];
    }

    public boolean isEmpty() {
        return this.usedSize==0;
    }

    private boolean isFull() {
        return this.usedSize==this.elem.length;
    }
}

这边就是我们用顺序表实现栈的过程,代码量不是很大实现起来也比较简单。

队列

概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾(Tail/Rear) 出队列:进行删除操作的一端称为队头。

 实现

基于单链表实现队列

/**
 * 利用单链表实现我们的队列
 * 首先创建我们的链表节点
 * */
class Node {
    public int val;
    public Node next;
    public Node(int val) {
        this.val = val;
    }
}
public class MyQueue {
    public Node head;
    public Node last;
    public void offer(int val) {
        Node node = new Node(val);
        if (this.head==null) {
            this.head = node;
            this.last = node;
        } else {
            this.last.next = node;
            this.last = this.last.next;
        }
    }
    public int pull() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空!");
        } else {
            int oldVal = this.head.val;
            this.head = this.head.next;
            return oldVal;
        }
    }
    public boolean isEmpty() {
        return this.head == null;
    }
    public int peek() {
        if (isEmpty()) {
            throw new RuntimeException("队列为空!");
        } else {
            return this.head.val;
        }
    }
}

循环队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列,环形队列通常使用数组实现。

 循环队列可以充分的利用我们的资源。

数组下标循环技巧

1. 下标最后再往后(offset 小于 array.length): index = (index + offset) % array.length。

2. 下标最前再往前(offset 小于 array.length): index = (index + array.length - offset) % array.length。

判断队列的空与满

队列为空:

队列的空很容易判断,只要当我们的front与rear相等的时候就是队列为空的时候。

队列为满:

1.我们可以用一个变量usedSize来记录我们队列现有的元素没入队一个元素就+1,出队就-1,当usedSize的大小和我们数组的大小相同的时候就是队列满的时候。

2.我们可以Boolean一个flag标记一下,我们rear入队的时候就给它置为true,front出队的时候就给它置为false,当我们的rear==front&&flag==true的时候就是队列满的时候。

3.我们可以用   (this.rear+1)%elem.length==this.front)  这条语句来判断一下队列是否是满的当返回true的时候就是满的,不过这样也导致了一个缺点那就是我们的队列但会空一个用不了。

代码

public class MyCircularQueue {
    private int[] elem;
    private int rear;
    private int front;
    public MyCircularQueue(int k) {
        this.elem = new int[k+1];
    }
    public boolean enQueue(int value) {
        if (isFull()) {
            return false;
        } else {
            this.elem[this.rear] = value;
            this.rear = (this.rear+1)%this.elem.length;
            return true;
        }
    }

    public boolean deQueue() {
        if (isEmpty()) {
            return false;
        } else {
            this.front = (this.front+1) % this.elem.length;
            return true;
        }
    }

    public int Front() {
        if (isEmpty()) {
            return -1;
        } else {
            return this.elem[this.front];
        }
    }

    public int Rear() {
        if (isEmpty()) {
            return -1;
        } else {
            if (this.rear==0) {
                int index = this.elem.length-1;
                return this.elem[index];
            } else {
                return this.elem[this.rear-1];
            }
        }
    }

    public boolean isEmpty() {
        return this.front==this.rear;
    }

    public boolean isFull() {
        if ((this.rear+1)%elem.length==this.front) {
            return true;
        } else {
            return false;
        }
    }
}

双端队列(Deque)

概念

双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

Java中的栈和队列

 在Java中我们的队列的底层是由双向链表来实现的。

Stack

方法解释
E push(E item)压栈
E pop()出栈
E peek()查看栈顶元素
boolean empty()判断栈是否为空

Queue

错误处理抛出异常返回特殊值
入队列add(e)offer(e)
出队列remove()poll()
队首元素element()peek()

Deque

  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值