栈与队列(详解)

日升时奋斗,日落时自省 

目录

一、栈

1.1栈的基本概念

 1.2栈的模拟实现

1.3栈的使用 

1.4栈的应用场景

 二、队列

2.1队列的概念

 2.2模拟实现队列

2.3队列的使用

 2.4循环队列


一、栈

1.1栈的基本概念

栈:是一种特殊的线性表,栈只允许在固定的一端进行插入和删除元素操作,进行数据删除和插入时,一端是栈顶,另一端是栈低,栈中遵循元素先入后出

压栈:就是将数据放入栈中。

出栈:栈的删除操作叫做出栈。弹出栈

 1.2栈的模拟实现

栈的底层实现时依靠顺序表也就是数组实现的,这里模拟实现也是数组构成的栈

 栈入通过这张图比较好理解

栈出下图解释:

 栈出并不是真的删除某个值,而是将有效值的个数减一。

问题?下次还会栈出吗,不会因为我们栈出有效栈的数据个数,下次push时就会将原来的数据覆盖

public class MyStack {
    public int[] elem; //建立当前数组 构建栈空间
    public int usedSize;   //计算当前栈中的个数
    public static final int DEFULT_SIZE=10;   //暂时给定栈中为10个空间
    public  MyStack(){
        this.elem=new int[DEFULT_SIZE];    //构造方法传值
    }

    public  int  push(int  val){   //入栈
        //1、入栈限制,栈是否满了
        //2、将传入的数据给数组,入栈结束
        if(isFull()){
            this.elem= Arrays.copyOf(this.elem,2*this.elem.length);   //如果空间不够,进行扩容
        }
        this.elem[usedSize]=val;    //将只当前值直接给数组的最后一位
        usedSize++;                 //数组个数加一
        return val;                 //直接返回当前传入值就行了
    }
    private boolean isFull(){    //栈满的条件  有效数据个数与数组长度相等
        return this.usedSize==elem.length;
    }
    public int pop(){    //出栈
        //1、栈是否为空  为空就抛出异常
        //2、栈出数据,将当前数据存给一个变量
        if(Empty()){
            throw new EmptyWrongExpection("为空");
        }
        int ret=this.elem[usedSize-1];   //usedSize-1表示的最后一个数据
        usedSize--;  //这里是栈出所以要删除 有效个数减减
        return ret;
    }
    public boolean  Empty(){  //为空条件 数据个数为零
        return this.usedSize==0;
    }
    public int peek(){   //探 栈顶元素 与栈出相近
        //1、先判断是否为空  为空抛出异常
        //2、后来在进行当前值返回即可
        if(Empty()){
            throw new EmptyWrongExpection("为空");
        }
        return this.elem[this.usedSize-1];
    }
}

1.3栈的使用 

模拟实现中,已经实现了栈出(push)、栈入(pop)、和探顶(peek)、检测栈空(empty)

方法功能
Stack()构造一个空的栈
E push(E e)将e入栈,并返回e
E pop()将栈顶元素出栈并返回
E peek()获取栈顶元素
int size()获取栈中有效元素个数
boolean empty()检测栈是否为空

 

 调用数据库中的函数库中的栈

1.4栈的应用场景

1. 若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是(C
A: 1,4,3,2 B: 2,3,4,1 C: 3,1,4,2 D: 3,4,2,1
 

 

 二、队列

2.1队列的概念

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

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


 2.2模拟实现队列

队列在库函数中是有双向链表实现的,我们这里模拟实现就用单链表来实现

public class MyQueue {    //单链表实现队列  以尾插来入队,从头开始出队
    static class  ListNode{
        public int val;
        public ListNode next;

        public ListNode(int val){
            this.val=val;
        }
    }
    public ListNode head;   //设置一个头结点
    public ListNode tail;   //设置一个尾结点
    public int usedSize;  //计算队列的个芜湖市
    public void offer(int val){    //插入队列,尾插
        ListNode node=new ListNode(val);
        if(head==null){   //队中没有东西的时候,直接尾插,要动用头和尾
            head=tail=node;
        }else{
            tail.next=node;  //没有特殊情况下,尾巴移动构成尾插
            tail=node;
        }
        usedSize++;   //当前是单链表实现的,所以对于
    }
    public int poll(){    //出队,头结点
        if(head==null){
            return -1;
        }
        int ret=head.val;
        head=head.next;
        if(head==null){  //特殊情况,当前只有一个的时候被覆盖掉了当前head就是null然而这时候tail也与head相同了,两个域都应该被置空
            tail=null;
        }
        usedSize--;
        return ret;
    }
    public int peek(){
        if(head==null){
            return -1;
        }
        return head.val;
    }
    public boolean empty(){
       return usedSize==0;
    }
    public int getUsedSize(){
        return  usedSize;
    }
}

2.3队列的使用

模拟队列中,实现了出队列,入队列,探队列头

方法功能
boolean offer(E e)入队列
E poll()出队列
peek()获取队头元素
int size()获取队列中有效元素个数
boolean isEmpty()检测队列是否为空

 2.4循环队列

循环队列有数组构成

public class MyQueue_Elem_Second {
    private int[] elem;
    private int usedSize;

    public int front;  //开头

    public int rear;   //末尾

    public MyQueue_Elem_Second(int k){
        elem=new int[k+1];     //为什么是k+1,使用数组循环队列就到导致有一个空间是空下来的
    }
    public boolean enQueue(int value) {   //入队
        if(isFull()){
            return  false;
        }
        elem[rear]=value;   //将当前传入值给数组的末尾
        rear=(rear+1)% elem.length;   //末尾以当前这种方法是为了,能够跳过7—》0的位置,构成循环
        return true;
    }
    public boolean isFull(){
        if((rear+1)% elem.length==front){   //判满的方法也是相同,当rear的下一个就是front  满
            return true;
        }
        return false;
    }
    public boolean deQueue() {     //出队
        if(isEmpty()){
            return false;
        }
        int ret=elem[front];
        front=(front+1)% elem.length;
        return true;
    }
    public boolean isEmpty(){   //判空如何判断  rear在开始与front在相同位置,只要头与尾相同为空
        if(rear ==front){
            return true;
        }
        return false;
    }
    public int Rear(){   //找当前尾位置的时候不能直接找,可能在循环处就找不到 rear-1
        if(isEmpty()){
            return -1;
        }
        int index=(rear+1)% elem.length==0? elem.length -1:rear-1;   //避免在循环处
        return elem[index];
    }
    public int Front(){   //为什么头位置不需要像位置一样麻烦
        if(isEmpty()){
            return -1;
        }
        return elem[front];   //本身的数据可以直接取,不需要
    }
}

队列循环的要点: 

 下标往后移动rear与front移动都不能直接+1,都会有从末尾到0的时候

所以向前的代码:

(rear+1)%数组长度

(front+1)%数组长度

三、队列与栈的区别

队列:数据是一端入队,另一端出队

原则:先入先出

栈:数据一端入栈,同一端出栈

原则:先入后出

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
数据结构是计算机存储、组织数据的方式,算法是解决问题的步骤和方法。数据结构和算法是计算机科学中最基础、最重要的两个领域之一。掌握数据结构和算法可以帮助我们更好地理解计算机科学的本质,提高编程能力,解决实际问题。 常见的数据结构包括数组、链表、队列、树、图等。常见的算法包括排序、查找、递归、分治、动态规划等。 在学习数据结构和算法时,需要掌握以下知识点: 1. 时间复杂度和空间复杂度:用来衡量算法的效率和资源消耗。 2. 数组:一种线性数据结构,用来存储一组相同类型的元素。 3. 链表:一种线性数据结构,用来存储一组元素,每个元素包含一个指向下一个元素的指针。 4. :一种后进先出(LIFO)的数据结构,用来存储一组元素。 5. 队列:一种先进先出(FIFO)的数据结构,用来存储一组元素。 6. 树:一种非线性数据结构,由节点和边组成,每个节点可以有多个子节点。 7. 图:一种非线性数据结构,由节点和边组成,每个节点可以有多个相邻节点。 8. 排序算法:用来将一组元素按照一定的顺序排列的算法,包括冒泡排序、选择排序、插入排序、快速排序、归并排序等。 9. 查找算法:用来在一组元素中查找指定元素的算法,包括线性查找、二分查找、哈希查找等。 10. 递归算法:一种通过调用自身来解决问题的算法。 11. 分治算法:一种将问题分解成多个子问题来解决的算法。 12. 动态规划算法:一种通过将问题分解成多个子问题来解决的算法,通常用于求解最优化问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值