慕课网liuyubobobo老师课程学习笔记---part2 :栈和队列

本文是liuyubobobo老师课程的学习笔记,主要探讨了栈和队列这两种数据结构。栈作为一种后进先出(LIFO)的数据结构,被用于括号匹配问题,通过Java Stack类实现。队列则是先进先出(FIFO)的数据结构,文中讲解了其基本操作和循环队列的实现,强调了循环队列在效率上的优势。
摘要由CSDN通过智能技术生成

1、栈
  栈也是一种线性结构,相比数组,栈对应的操作是数组的子集。栈只能从一端添加元素,也只能从一端取出元素,这一端称为栈顶。
  栈是一种后进先出的数据结构——Last In First Out(LIFO),在计算机的世界里,栈拥有着不可思议的作用。

栈的应用
	1)无处不在的Undo操作(撤销);
	2)程序调用的系统栈。(子过程子逻辑的调用)

栈的实现

在这里插入图片描述
  这部分参考StackTest项目,代码如下:

package com.lkj;

/*
复杂度分析:全部5个方法的时间复杂度都是O(1)。另外,push以及pop方法既是会触发栈的容积变化,但是均摊复杂度依然是O(1)
    boolean idEmpty();
    int getSize();
    void push(E e);//入栈
    E pop();//出栈
    E peek();//获取栈顶的元素
 */
public class ArrayStack<E> implements Stack<E>
{
   
    /*
        注意,我们是基于前面的动态数组来创建我们的栈的,因此我们初始化栈的时候,必须先初始化一个动态数组。
     */
    //有一个成员变量:类型是我们前面创建的动态数组
    Array<E> array;

//------------------------------------------构造函数
    public ArrayStack(int capacity)//因为我们的栈是基于动态数组实现的,因此就有容积这个概念
    {
   
        array = new Array<E>(capacity);//首先创建一个容量为capacity的动态数组
    }

    public ArrayStack()
    {
   
        array = new Array<E>();//创建一个默认容量的动态数组(默认为10)
    }

    @Override
    public boolean idEmpty()
    {
   //数组是空的,那么依靠数组实现的栈也是空的
        return array.isEmpty();
    }

    @Override
    public int getSize()
    {
   //数组的元素个数等于栈的元素个数
        return array.getSize();
    }

    //获取栈的容积——这个方法Stack接口并没有,因为Stack接口与栈的具体实现无关,
    // 只有我们通过动态数组实现栈,才有容积这个说法。因此这个方法是ArrayStack特有的
    public int getCapacity()
    {
   
        return array.getCapacity();
    }

//----------------------------------------------------------------------入栈出栈,以及获取栈顶元素的方法
    /**
     * 1、根据栈先进后出的原则,我们在数组的末尾添加,就必须在数组的末尾取出,这样才满足先进后出。(栈顶是在数组的末尾)
     * 2、另外,由于我们送他数组Array中会根据元素个数以及数组容积自动进行扩容和缩容,因此用户不需要考虑空间够不够使用的问题。
     * 3、我们不需要判断栈是否为空,因为如果栈为空,相当于动态数组为空,那么操作出错的时候自然会抛出异常。
     * 4、我们没有获取栈中任意角标元素的方法:get(index),因为对于栈这种数据结构,只能看到栈顶的元素,而无法获取栈中的某个元素。
     *      当然,栈也无法实现将元素插入栈中某一个位置:add(int index , E e),或者删除栈中任意位置的元素:remove(int index)。
     *      既对于栈来说,我们只能往栈顶入栈(push)或者出栈元素(pop),或者获取栈顶元素(peek),其他位置的操作不能实现。
     */
    @Override
    public void push(E e)
    {
   //往数组的末尾添加元素
        array.addLast(e);
    }

    @Override
    public E pop()
    {
   //在数组末尾删除元素
        return array.removeLast();
    }

    @Override
    public E peek()
    {
   //此处,栈顶是在数组的末尾,因此要getLast
        return array.getLast();
    }

//------------------------------------------
    @Override
    public String toString()
    {
   
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        //注意,此时栈的元素个数相当于数组的Array的size
        // 此处Array不是java的数组,而是我们自己定义的数组类,因此不能使用Array[x]、Array.length这种写法,而要使用Array的get或者getSize方法
        for (int i = 0; i < array.getSize() ; i++)
        {
   
            sb.append(array.get(i));
            if(i != array.getSize()-1)
                sb.append(",");
        }
        sb.append("] top" );//top表示栈顶在尾部
        return sb.toString();
    }
}

栈的一个应用——括号匹配

  在完成括号匹配应用的时候,我们同时解决LeetCode中的一个问题:
在这里插入图片描述
  思路:我们使用栈来完成这个功能。
1)对于这个只包含括号的字符串,首先我们利用一个循环,从头开始读取每个字符,如果这个字符是“(”、“[”、“{” 这类左括号,我们将这个字符推入栈;
2)当读取到的字符不是左括号而是右括号的时候,我们就先判断栈是否为空,如果栈为空,而这里有一个右括号,说明字符串无效,返回false;(这种情况是前面左括号不够而右括号过多,如:()}
3)如果栈不为null,我们将栈顶的元素出栈,判断这个右括号与栈顶的左括号是否是同一个类型。如果不是同一个类型,说明这个字符串无效,返回false;(这种情况是左括号与右括号不匹配,如:([)] ),如果2个括号是同一个类型的,继续读取下一个字符,注意,取出元素的时候栈顶的元素已经出栈。
4)当字符串的字符读取完毕后,我们判断栈里面还有没有元素,既判断栈是否为null,如果还有元素,字符串无效,返回false。(这种情况是前面左括号过多而右括号不够,如:({} )如果没有元素,说明字符串有效,返回true。

  • 注意,需要排除左括号与右括号不匹配,左括号过多,右括号过多3种错误情况。
  • 我们是一直在排除错误的情况,如果循环后没有返回false,说明字符串有效,所有错误情况被排除,返回true

  首先,使用java提供的Stack类解决。代码如下(参考项目StackResolveProblem)

import java.util.Stack;

public class Solution
{
   
    public boolean isValid(String s) {
   
        //先创建一个栈,注意这个栈存储的是char类型的字符数据</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值