Java 数据结构 栈和对队列-学习笔记

目录

 

1.栈(Stack)

1.1 概念

1.2  栈的实现

2.队列(Queue)

 2.1 概念

 2.2 队列的实现

 2.3  循环队列

 2.3.1 概念

 2.3.2  循环队列的实现

3. 双端队列 (Deque)


1.栈(Stack)

1.1 概念

栈是一种特殊的线性表,栈只允许再固定的一端进行插入和删除元素的操作。栈中的数据遵循先进后出LIFO(last in first out)的原则。

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

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

我们常见的栈的操作有:方法调用栈的过程;浏览器的前进与后退; 编辑器中的撤回; 代码编辑器中括号的匹配; 算术运算符号的优先级。

 

  栈的核心操作:

1、push():向栈中添加元素       

2、pop():移除栈顶元素

3、peek():查看栈顶元素但不删除                

1.2  栈的实现

 栈的底层实现有两种:

1、基于数组的实现:顺序栈    

2、基于链表的实现:链式栈

使用顺序表实现栈:

package stack_quene.stack.stack;

import java.util.Arrays;
import java.util.NoSuchElementException;

public class Stack<E> {
    public boolean isEmpty;
    private E[] elementdata;
    private int size;

    public Stack() {
        elementdata = (E[]) new Object[10];
    }

    public Stack(int initCap) {
        elementdata = (E[]) new Object[initCap];
    }

    //入栈操作
    public void push(E value) {
        //扩容
        if (size == elementdata.length) {
            grow();
        }
        elementdata[size] = value;
        size++;
    }

    //出栈操作
    public E pop() {
        if (getSize() == 0) {
            throw new NoSuchElementException("栈为空");
        }
        E oldValue = elementdata[size - 1];
        size--;
        elementdata[size] = null;
        return oldValue;

    }

    //查看栈顶元素但不删除
    public E peek() {
        if (getSize() == 0) {
            throw new NoSuchElementException("栈为空");
        }
        return elementdata[size - 1];

    }

    public int getSize() {
        return size;

    }

    //扩容操作
    public void grow() {
        int oldValue = this.elementdata.length;
        int newValue = oldValue << 1;
        this.elementdata = Arrays.copyOf(elementdata, newValue);
    }


    @Override
    public String toString() {
        StringBuilder sb=new StringBuilder();
        sb.append("[");
        for (int i = 0; i < size; i++) {
            sb.append(elementdata[i]);
            if(i!=size-1){
                sb.append(",");
            }
        }
         sb.append("] top");
        return sb.toString();
    }

    public boolean isEmpty() {
        return false;
    }
}

2.队列(Queue)

2.1 概念

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

 队列的核心操作:

1.offer():入队操作;

2.poll():出队操作;

3.peek():查看队首元素,但不出队。

 

 2.2 队列的实现

队列的两种底层实现:

1.基于数组的队列:循环队列

2.基于链表的队列 

队列使用链表实现更加优化一些,因为如果使用数组结构,出队列时在数组头出数据,那么在删除后后面所有元素都需要向前移动,效率比较低。

package stack_quene.stack.quene.impl;

import stack_quene.stack.quene.Queue;

import java.util.NoSuchElementException;

public class LinkedQuene implements Queue {
    private Node head;
    private Node tail;
    private int size;
    private class Node{
        private int data;
        private Node next;

        public Node(int data) {
            this.data = data;
        }
    }

    /**
     * 队首出,队尾进
     * @param value
     */
    @Override
    public void offer(int value) {
        Node node=new Node(value);
        if(head==null){
            head=tail=node;
        }else {
            tail.next = node;
            tail = node;
        }
        size++;
    }

    //出队列操作
    @Override
    public int poll() {
        if(size==0){
            throw new NoSuchElementException("队列为空");
        }
        int oldValue=head.data;
        Node node=head;
        head=head.next;
        node.next=null;
        size--;
        return oldValue;
    }

    //查看队首元素,但不删除的操作
    @Override
    public int peek() {
        if(size==0){
            throw new NoSuchElementException("队列为空");
        }
        return head.data;
    }

    
    @Override
    public boolean isEmpty() {
        return false;
    }

    //打印输出队列
    @Override
    public String toString() {
       StringBuilder stringBuilder=new StringBuilder();
       stringBuilder.append("front [");
        Node node=head;
        while(node!=null){
            stringBuilder.append(node.data);
            if(node.next!=null){
                stringBuilder.append(",");
            }
            node=node.next;
        }
        stringBuilder.append("] top");
        return stringBuilder.toString();
    }
}

 2.3  循环队列

2.3.1 概念

在循环队列中我们规定:front指向循环队列的第一个元素的索引; tail指向循环队列的最后一个元素的下一个元素的索引(为了方便插入元素,array[tail]=value)。

 循环队列的front和tail下标的移动与普通数组元素的下标移动不一样,不能再简单的进行+1操作,因为当tail的下标移动到数组的最后一个位置时,在数组未存满的情况下,需要继续循环移动到数组的第一个位置,继续从头开始入队。

所以front和tail的移动规则是:front=(front+1)%array.length ,tail=(tail+1)%array.length

 

  如何判断循环队列的空or满呢?

 1.判断数组是否为空: front==tail

 

 2.判断数组是否已满:front=(tail+1)%array.length,因此我们规定在循环队列中浪费一个空间,这个空间不存储元素,为了区分空和满

 2.3.2  循环队列的实现

package stack_quene.stack.quene.impl;

import stack_quene.stack.quene.Queue;

public class LoopQueue implements Queue {
    private int[] data;
    //有效元素个数
    private int size;
    private int front;
    private int tail;

    public LoopQueue(int k) {
        data=new int[k+1];
    }

    @Override
    public void offer(int value) {
        //判断循环队列是否已满
        if(isFull()){
            System.out.println("queue is full");
            return;
        }
        data[tail]=value;
        tail=(tail+1)%data.length;
        size++;

    }

    @Override
    public int poll() {
        //判断循环队列是否为空
        if(isEmpty()){
            System.out.println("queue is empty");
            return -1;
        }
        int value=data[front];
        front=(front+1)%data.length;
        size--;
        return value;
    }

    @Override
    public int peek() {
        if (isEmpty()){
            System.out.println("queue is empty");
        }
        return data[front];
    }

    //如何查看队尾元素
    public int getTail(){
        if (isEmpty()){
            System.out.println("queue is empty");
        }
        int index=tail==0?data.length-1:tail-1;
        return data[index];
    }

    @Override
    public boolean isEmpty() {
        if(front==tail){
            return true;
        }
        return false;
    }

    public boolean isFull(){
        if((tail+1)%data.length==front){
            return true;
        }
        return false;
    }
    public int  getSize(){
        return size;
    }

    //遍历数组
    public String toString(){
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("front [");
        for (int i = front; i !=tail ;) {
            stringBuilder.append(data[i]);
            if(i!=tail-1){
                stringBuilder.append(",");
            }
            i=(i+1)%data.length;
        }
        stringBuilder.append("] tail");
        return stringBuilder.toString();
    }


}

3. 双端队列 (Deque)

双端队列是指允许两端都可以进行入队和出队操作的队列。

这就是关于栈和队列的所有基本知识~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值