java数组/链表实现栈和队列

一、栈结构介绍

​ 栈(stack) 是限定仅在表尾进行插入或删除操作和线性表(只有一端口能进出数据),对栈来说表尾和表头有特殊含义,表尾被称为栈顶,表头被称为栈底,没有元素的空表称为空栈,元素数量达到栈的容量称为满栈,数据添加到栈中叫入栈、压栈,数据从栈中删除叫出栈、弹栈,由于栈元素特殊添加和删除的规则,所以栈的元素会先进后出的现象,简称为LIFO(Last in first out)。

数组——代码实现栈:

1、私有变量和构造方法

    private static final int CAPACITY = 20;//栈容量
    private int topOfStack;//栈顶指针
    private  Object arrayStack[];
    public MyArrayStack(){//构造方法
        topOfStack = -1;
        arrayStack = new Object[CAPACITY];
    }

我们创建一个容量为20的数组,并用一个指针来记录栈顶元素。我们在构造方法里初始化栈顶指针为-1,代表着栈为空。

2、入栈

  /***** 入栈 *****/
    @Override
    public boolean push(Object o) {
        if(topOfStack >= (CAPACITY-1)){
            System.out.println("栈满了");
            return false;
        }
        arrayStack[++topOfStack] = o;
        return true;
    }

入栈的思路就是先将栈顶指针向上移一位,再直接赋值,前提需判断该栈是否满,当然栈满了,是不允许再进栈的。

3、出栈

/***** 出栈 *****/
    @Override
    public Object pop() {
        if(topOfStack<0){
            System.out.println("栈为空");
        }
        Object old = arrayStack[topOfStack];
        arrayStack[topOfStack--] = null;
        return old;
    }

出栈的思路和入栈差不多,先判断栈是否为空,再将栈顶元素赋值给一个变量并将其记录,将其设置为空指针向下移一位。

4、

   //查看当前栈顶元素
    @Override
    public Object peek() {
        if(topOfStack<0){
            System.out.println("栈为空");
        }

        return arrayStack[topOfStack];
    }
  @Override
    public int size() {
        return topOfStack+1;
    }

    @Override
    public boolean isEmpty() {
        return topOfStack<0;
    }

链表——代码实现栈:(用双向链表)

1、链表节点类

  static class Node<E>{
        Object element;
        Node prev;
        Node next;

        public Node(Object element){
            this.element = element;
        }
    }

2、私有变量和构造方法

    private Node<E> head;
    private Node<E> tail;
    private int size;
    private static final int MAX_CAP = 100;

    public MyLinkedStack(){
        head = new Node<>(null);
        tail = new Node<>(null);
        head.next = tail;
        tail.prev = head;
        size = 0;
    }

我们设置最大容量为100的栈,在构造方法里首先将其头尾节点的值设置为null,并互相指向对方。

3、进栈

 /***** 进栈 *****/
    @Override
    public boolean push(Object o) {
        if(size<MAX_CAP) {
            Node<E> x = new Node<>(o);
            Node<E> temp = head.next;
            //head temp
            x.prev = head;
            x.next = temp;

            head.next = x;
            temp.prev = x;
            size++;
            return true;
        }
        return false;
    }

思路是先判断栈是否满,然后创建一个节点将要入栈的值装入,再运用头指针获取第一个节点(头指针后面的那个节点),将新节点加入,成为第一个节点。(把头节点的prev,next分别指向head,第一个节点。再将头节点的next指向新节点,将第一个节点的prev也指向新节点)。

4、出栈

/***** 出栈 *****/

    @Override
    public Object pop() {
        if (size>=1) {
            Node<E> x = head.next;
            Node<E> temp = x.next;

            head.next = temp;
            temp.prev = head;
            Object need = x.element;
            x.prev = x.next =null;
            size--;
            return need;
        }
        return null;
    }

出栈和进栈思路差不多,主要思路就是将第一个节点删除,删除前把值记录下来并返回。

5、


    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size==0;
    }
 /***** 查看栈顶元素 *****/
    @Override
    public Object peek() {
        return head.next.element;
    }

二、队列介绍

​ 它与栈刚好相反,是一种先进先出的线性表,它有两个端口添加、删除元素,一个端口只能添加元素,被称为入队,该端口被为队尾,另一个端口只能删除,被称为出队,该端口被称为队头。

链表——实现队列:(双链表)

package pgs0205;

public class MLinkedQueue<E> {
    public class Node<E>{
        E element;
        Node prev;
        Node next;
        public Node(E element){
            this.element = element;
        }
    }
    private static final int MAX_CAP = 20;
    private Node<E> head;
    private Node<E> tail;
    private int size;
    public MLinkedQueue(){
        head = new Node<>(null);
        tail = new Node<>(null);
        head.next = tail;
        tail.prev = head;
        size = 0;
    }
    /***** 入队 *****/
    public boolean enqueue(E element){
        if(size<MAX_CAP) {
            Node<E> x = new Node<>(element);
            Node<E> temp = tail.prev;

            x.prev = temp;
            x.next = tail;
            temp.next = x;
            tail.prev = x;
            size++;

            return true;
        }
        return false;
    }
    /***** 出队 *****/
    public E dequeue(){
        if(size >=1){
            size--;
            return (E) head.next.element;
        }
        return null;
    }
    /***** 查看队列第一个 *****/

    public E getFront(){
        return (E) head.next.element;
    }
    /***** 获取队列长队 *****/
    public int getSize(){
        return size;
    }
    /***** 判断是否为空 *****/
    public boolean isEmpty(){
        return size==0;
    }

}

主要把握队列的性质(先进先出),然后注意链表的增删。

数组——实现队列:

package pgs0205;

public class MyArrayQueue<E> {
    private static final int MAX_CAP = 20;
    private Object arrayQueue[];
    private int topOfQueue;
    private int botOfQueue;

    public MyArrayQueue() {
        arrayQueue = new Object[MAX_CAP];
    }

    /***** 入队 *****/
    public void enqueue(E element) {
        if (isFull()) {
            System.out.println("队满");
        }
        arrayQueue[botOfQueue] = element;
        botOfQueue = (botOfQueue + 1) % MAX_CAP;
    }

    /***** 出队 *****/
    public E dequeue(){
        if(isEmpty()){
            throw new RuntimeException("队列为空!");
        }
        E temp = (E) arrayQueue[topOfQueue];
        topOfQueue = (topOfQueue+1)%MAX_CAP;
        return temp;
    }

    /***** 查看对头元素 *****/
    public E getFront() {
        if(isFull()){
            throw new RuntimeException("队列满了");
        }
        return (E) arrayQueue[topOfQueue];
    }

    /***** 获取队列长度 *****/
    //查看队列的第一个元素
    public E HeadNum(){
        if(isEmpty()){
            throw new RuntimeException("队列为空!");
        }
        return (E) arrayQueue[topOfQueue];
    }

    /***** 判断是否为空 *****/
    public boolean isEmpty() {
        return topOfQueue==botOfQueue;
    }

    /***** 判断是否满 *****/
    public boolean isFull() {
        return (botOfQueue + 1) % MAX_CAP == topOfQueue;  //最后一个位置没用到
    }
    /***** 显示队列所有数据 *****/
    //显示队列的所有数据
    public void ShowQueue(){
        if(isEmpty()){
            System.out.println("队列中没有数据");
            return;
        }
        for(int i = topOfQueue;i < topOfQueue+CountQueue();i++){
            System.out.println(arrayQueue[i%MAX_CAP]);
        }
    }
    /***** 队列中有效元素个数 *****/
    public int CountQueue(){
        if(isEmpty()){
            return 0;
        }
        return (botOfQueue+MAX_CAP-topOfQueue)%MAX_CAP;
    }

//    本文中有几个需要注意的公式,就是判断队列是否满了:
//
//            (topOfQueue+1)%MAX_CAP == botOfQueue
//    还要就是队尾指针和队头指针移动的操作:
//
//    topOfQueue = (topOfQueue+1)%MAX_CAP;
//    查看队列中有效元素的个数:
//
//            (topOfQueue+MAX_CAP-botOfQueue)%MAX_CAP
//    还有就是遍历队列:
//
//            for(int i = botOfQueue;i < botOfQueue+CountQueue();i++){
//        System.out.println(arrayQueue[i%MAX_CAP]);
//    }
}

运用固定大小的数组实现队列,首先我们给定大小为20的数组,入队指针和出队指针都指向数组第一个位置即索引为0,当入队一个元素时,botOfQueue指针就会往后移一位,当出队一个元素时,topOfQueue指针也会往后移一位,这样数组前部分位置都空出来了,当位置不够时,指针又回到索引0位置,这样这个固定大小数组就得以实现重复使用。

注意:判断队列是否满 isFull();方法,判断依据是当botOfQueue指针+1刚好是topOfQueue指针位置则队列就满了。因此本队列真实大小容量为19。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值