数据结构---栈和队列

栈和队列。这两者都属于逻辑结构,它们的物理实现既可以利用数组,也可以利用链表来完成。

栈(stack)是一种线性数据结构,它就像一个上图所示的放入乒乓球的圆筒容器,栈中的元素只能先入后出(First In Last Out,简称FILO)。
最早进入的元素存放的位置叫作栈底(bottom),最后进入的元素存放的位置叫作栈顶
(top)。

在这里插入图片描述
在这里插入图片描述
栈的数组实现
在这里插入图片描述
栈的链表实现
在这里插入图片描述

入栈

入栈操作(push)就是把新元素放入栈中,只允许从栈顶一侧放入元素,新元素的位置将会成为新的栈顶。

出栈

出栈操作(pop)就是把元素从栈中弹出,只有栈顶元素才允许出栈,出栈元素的前一个元素将会成为新的栈顶。

栈的JAVA实现

package dataStructure.myStack;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.EmptyStackException;

public class myStack <E>{
    private Object[]arr;
    //数组默认长度
    private int stackLength=4;
    private int size;
    //指针
    private int index = -1;
    //判断栈是否为空
    public boolean empty(){
        return this.size==0;
    }
    //获取栈顶元素
    public E pop(){
        if(this.index==-1){
            throw new IndexOutOfBoundsException("空栈,无法取元素");
        }
        this.size--;

        return (E) this.arr[index--];
    }

    /**
     * 数组初始化或者以 1.5 倍容量对数组扩容
     */
    private void capacity(){
        if(this.arr==null){
            this.arr = new Object[this.stackLength];
        }
        if(this.size-(this.stackLength-1)>=0){
            this.stackLength = this.stackLength+this.stackLength/2;
            this.arr = Arrays.copyOf(this.arr,this.stackLength);

        }
    }

    //向栈容器添加元素
    public E push(E item){
        this.capacity();
        this.arr[++index]=item;
        this.size++;
        return item;
    }

    public static void main(String[] args) {
        myStack<String> myStack = new myStack<>();
        myStack.push("a");
        myStack.push("b");
        myStack.push("c");
        System.out.println(myStack.pop());
        System.out.println(myStack.empty());
        System.out.println(myStack.pop());
        System.out.println(myStack.pop());
        System.out.println(myStack.empty());
        System.out.println(myStack.pop());

    }

}

队列

队列(queue)是一种线性数据结构,它的特征和行驶车辆的单行隧道很相似。不同于栈的先入后出,队列中的元素只能先入先出(First In First Out,简称(FIFO)。队列的出口端叫作队头(front),队列的入口端叫作队尾(rear)。

队列这种数据结构既可以用数组来实现,也可以用链表来实现。

队列数组实现
在这里插入图片描述

队列链表实现
在这里插入图片描述

入队

入队(enqueue)就是把新元素放入队列中,只允许在队尾的位置放入元素,新元素的下一个位置将会成为新的队尾。
在这里插入图片描述

出队

出队操作(dequeue)就是把元素移出队列,只允许在队头一侧移出元素,出队元素的后一个元素将会成为新的队头。
在这里插入图片描述

循环队列

数组实现的队列可以采用循环队列的方式来维持队列容量的恒定。
以利用已出队元素留下的空间,让队尾指针重新指回数组的首位。
在物理存储上,队尾的位置也可以在队头之前。当再有元素入队时,将其放入数组的首位,队尾指针继续后移即可。
队列满的条件:(队尾下标+1)%数组长度 = 队头下标
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

循环队列JAVA实现

package dataStructure.myQueue;

public class circleQueue {
    private int front;//队头指针
    private int rear;//对尾指针
    private int capacity;//队列容量
    private int[] array;

    public circleQueue(int capacity) {
        this.capacity = capacity;
        this.array = new int[this.capacity];
    }

    public circleQueue() {

    }

    /**
     * 出队
     * @return
     * @throws Exception
     */
    public int deQueue() throws Exception{
        if(rear==front){
          throw new Exception("队列已空");
        }
        //队头出队
        int deQueueElement = array[front];
        front = (front+1)%array.length;
        return deQueueElement;
    }

    /**
     * 入队
     * @param element
     * @throws Exception
     */
    public void enQueue(int element) throws Exception{
        if((rear+1)%array.length==front){
            throw new Exception("队列已满!");
        }
        array[rear]=element;
        rear = (rear+1)%array.length;
    }

    /**
     * 输出队列
     */
    public void output(){
        for (int i = front;i!=rear;i=(i+1)%array.length){
            System.out.println(array[i]);
        }
    }

    public static void main(String[] args) throws Exception {
        circleQueue circleQueue = new circleQueue(6);
        circleQueue.enQueue(2);
        circleQueue.enQueue(4);
        circleQueue.enQueue(7);
        circleQueue.enQueue(100);
        System.out.println("队列元素为");
        circleQueue.output();
        System.out.println("--------");
        circleQueue.deQueue();
        circleQueue.deQueue();
        circleQueue.deQueue();
        System.out.println("队列元素为");
        circleQueue.output();
        System.out.println("--------");
        circleQueue.enQueue(12);
        circleQueue.enQueue(14);
        circleQueue.enQueue(16);
        circleQueue.enQueue(120);
        System.out.println("队列元素为");
        circleQueue.output();
        System.out.println("--------");
    }
}

栈和队列的应用

栈:栈通常用于对“历史”的回溯,也就是逆流而上追溯“历史”。

  1. 实现递归逻辑
  2. 导航

在这里插入图片描述
在这里插入图片描述
队列:是按照“历史”顺序,把“历史”重演一遍。

  1. 多线程中,争夺公平锁的等待队列,就是按照访问顺序来决定线程在队列中的次序的。
  2. 网络爬虫实现网站抓取时,也是把待抓取的网站URL存入队列中,再按照存入队列的顺序来依次抓取和解析的。

双端队列

双端队列:综合了栈和队列的优点,对双端队列来说,从队头一端可以入队或出队,从队尾一端也可以入队或出队。
在这里插入图片描述

优先队列

谁的优先级最高,谁先出队。
它是基于二叉堆来实现的。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值