JAVA用链表实现栈以及括号匹配问题


本次将采用链表的方式进行java中栈的实现

一、栈的实现


首先,我们要定义一个结点类

 

 private class Node{
        public T item;
        public Node next;
        public Node(T item, Node next){
            this.item=item;
            this.next=next;
        }
    }

不用多讲,下面我们定义一个头结点和一个整数用来记录栈内元素个数

 //记录一个首结点
    private Node head;
    //记录元素个数
    private  int N;

首先对头结点和N进行初始化

 

//对head和N进行初始化
    public Stack(){
        this.N=0;
        this.head=new Node(null,null);
    }

我们只需要把N等于0,把头结点内的数据为空,并让其下一个结点为空即可

接下来我们实现栈内元素个数的获取

 

//获取栈中元素个数
    public int size(){
        return  N;
    }

很简单,就是N的大小

下面进行元素的压入,比如说我们想让元素t压进栈内

就需要如下操作

一、1元素的压入

//把t元素压入栈
    public void push(T t) {
        //找到head指向的下一个结点
            Node oldNode=head.next;
            //创建一个新的结点,存储t
            Node newNode = new Node(t, null);
            //让原来的头结点指向新的结点
            head.next=newNode;
            //新的结点指向原来的第一个结点
            newNode.next=oldNode;
            //最后别忘了栈内元素加一
        N++;

    }

如代码块展示,根据栈的特点,先进后出,所以我们要把新的结点添加到头结点之后,同时让新结点指向原来的第一个结点,让头结点指向新的结点,同时不要忘了N是记录栈内元素个数的,添加一个新元素后要加一

下面来看栈顶元素的弹出

一、2栈顶元素的弹出


栈顶元素即我们最新压入的那个元素,要对其进行弹出,只要把头结点指向我们要弹出元素的结点的下一个结点即可,不过在此,我们不要忘了,若栈本身为空,那么我们弹出的也为空

 

public T pop(){
        //如果栈为空的话,即N=0的话
        if(N==0){
            //直接返回空即可
            return null;
        }
        //当栈不为空时
        //先找到第一个结点
        Node node=head.next;
        //让头结点指向结点的下一个结点即可
        head.next=node.next;
        //别忘了栈内元素个数减一
        N--;
        //最后返回弹出的元素值
        return node.item;
    }

最后,返回弹出的栈顶元素的值,并把栈内元素个数减一

下面我们介绍一下对栈的遍历方法

一、3栈的遍历方法


对此我们可以连接Iterable接口进行遍历

当然,首先我们要重写iterator方法

//重写iterator方法
    @Override
    public Iterator<T> iterator() {
        return new AIterator();
    }
    //创建一个AIterator类用来进行重写Iterator方法
    private class AIterator implements Iterator{
        //创建一个内部变量 n用来记录每次记录的当前结点
        private Node n;
        //创建一个构造方法
        public AIterator(){
            //初始情况下n=head
            this.n=head;
        }

        @Override
        //判断是否有下一个结点
        public boolean hasNext() {
            //只需要知道n的下一个结点是否等于null即可
            return n.next!=null;
        }

        @Override
        //得到n的下个结点的数据
        public Object next() {
            n=n.next;
            //直接返回n.item即可
            return n.item;
        }
    }

如代码块所示,我们重写了hasNext方法和next方法
下面给出源码

一、4源码

package linear;

import java.util.Iterator;
//利用Iterable接口进行遍历
public class Stack<T> implements Iterable<T>{
    //记录一个首结点
    private Node head;
    //记录元素个数
    private  int N;
    //创建一个结点类
    private class Node{
        public T item;
        public Node next;
        public Node(T item, Node next){
            this.item=item;
            this.next=next;
        }
    }
    //对head和N进行初始化
    public Stack(){
        this.N=0;
        this.head=new Node(null,null);
    }
    //判断当前栈中元素是否为0
    public boolean isEmpty(){
        return N==0;
    }
    //获取栈中元素个数
    public int size(){
        return  N;
    }
    //把t元素压入栈
    public void push(T t) {
        //找到head指向的下一个结点
            Node oldNode=head.next;
            //创建一个新的结点,存储t
            Node newNode = new Node(t, null);
            //让原来的头结点指向新的结点
            head.next=newNode;
            //新的结点指向原来的第一个结点
            newNode.next=oldNode;
            //最后别忘了栈内元素加一
        N++;

    }
    //弹出栈顶元素
    public T pop(){
        //如果栈为空的话,即N=0的话
        if(N==0){
            //直接返回空即可
            return null;
        }
        //当栈不为空时
        //先找到第一个结点
        Node node=head.next;
        //让头结点指向结点的下一个结点即可
        head.next=node.next;
        //别忘了栈内元素个数减一
        N--;
        //最后返回弹出的元素值
        return node.item;
    }
    //重写iterator方法
    @Override
    public Iterator<T> iterator() {
        return new AIterator();
    }
    //创建一个AIterator类用来进行重写Iterator方法
    private class AIterator implements Iterator{
        //创建一个内部变量 n用来记录每次记录的当前结点
        private Node n;
        //创建一个构造方法
        public AIterator(){
            //初始情况下n=head
            this.n=head;
        }

        @Override
        //判断是否有下一个结点
        public boolean hasNext() {
            //只需要知道n的下一个结点是否等于null即可
            return n.next!=null;
        }

        @Override
        //得到n的下个结点的数据
        public Object next() {
            n=n.next;
            //直接返回n.item即可
            return n.item;
        }
    }

}

二、括号匹配问题


下面看下问题

给定一个包括  '(' 和  ')'  以及其他字符的字符串 ,判断字符串中的  '('  和  ')'  是否成队出现,若成对出现则返回ture,否则返回false

下面给出问题分析

 

 这题我们用栈来解决

下面给出实现方法的图解

 

可以看到

我们先创建一个栈来接收字符串里面的字符,不过我们只存储  '('  

然后我们从左往右依次进行遍历字符串,得到每个字符

下面进行判断

如果字符为  '('  则把改字符压入栈内,若不是

则接着判断

如果字符为  ')' 则从栈内弹出一个元素(栈内存储的都是字符 '('  )若不是

则进行下一个字符的比较

其中还要判断弹出的元素是否为null,若为null则证明没有成对出现,返回false

若不为null,则进行下一个字符串的比较

最后遍历完成后

如果栈内元素为空,则证明成对出现,返回true

若不为空,则证明栈内还有  '('   的剩余,没有成对出现,返回false

下面看下代码的实现

二、1代码实现

public static boolean BracketsMatchTest01(String a){
        //创建栈对象,用来存储字符串
        Stack<String> stack=new Stack<>();
        //建立for循环用来遍历栈
        for(int i=0;i<a.length();i++){
            //建立一个字符串用来接a字符串的每个字符,要在后面加一个空符号
            String chara = a.charAt(i)+"";
            //当给出的字符为(时,让(压入到栈中
            if (chara.equals("(")){
                stack.push(chara);
            }
            //当给出的字符为)时,从栈里面弹出一个字符
            else if(chara.equals(")")){
                String ss= stack.pop();
                //当弹出的字符为空时,证明(和)不匹配,返回false
                if(ss==null){
                    return false;
                }
            }
        }
        //判断栈最后剩余的个数,若栈为空,则证明(和)匹配
        if(stack.size()==0){
            return true;
        }
        //若栈不为空,则证明(和)不匹配
        else {
            return false;
        }

    }

我们调用一个测试用例来实验一下,看结果是否正确

public class BracketsMatchTest {
    public static void main(String[] args) {
        String c="()()()()()()()(((()))))";
        if(BracketsMatchTest01(c)){
            System.out.println("true");
        }
        else {
            System.out.println("false");
        }
    }
}

不难看出,结果为false

下面看下测试结果

 

 结果为false

证明我们的代码完成

问题解决

这道题在力扣上面有原题,有兴趣的小伙伴可以去力扣上面进行查找

可以通过不同的方法进行实现,这只是其中一种方式

好了,本次就到这里结束

希望各位看官多多支持!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南之炎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值