数据结构——栈

原文1
原文2

什么是栈

栈相对于数组结构做了一些限制。在使用数组结构的时候,我们可以任意的取出数组内的任何元素,也可以随意在指定位置插入元素,而却对元素的获取与插入做了一些限制

栈只允许访问一个数据项:即最后插入的数据。移除这个数据项后才能访问倒数第二个插入的数据项。它是一种后进先出的数据结构。就好像打手枪,你的子弹夹,先装进弹夹的子弹,最后被打出来(左轮另说)。

代码实现

只对栈最基本的操作:出栈、入栈等操作进行了简单实现,没有对可能的异常进行处理。

public class Stack<E> {
    private int size; //栈的大小
    private int top; //栈顶元素下标
    private E[] element; //栈容器
    private int elementNum; //栈内元素

    public Stack() {
        this(10); //默认大小为10
    }

    public Stack(int size) {
        this.element = (E[])new Object[size];
        top = -1;
        this.size = size;
    }

    //入栈并返回入栈元素,栈顶下标加1,栈内元素加1
    public E push(E element) {
        this.element[++top] = element;
        elementNum++;
        return element;
    }

    //出栈并返回栈顶元素,栈顶下标减1,栈内元素减1
    public E pop() {
        elementNum--;
        return this.element[top--];
    }

    //返回栈顶元素
    public E peek() {
        return this.element[top];
    }

    //判断栈是否为空
    public boolean isEmpty() {
        return top == -1;
    }

    //返回栈内元素个数
    public int size() {
        return this.elementNum;
    }

    //toString方法
    @Override
    public String toString() {
        if (isEmpty()) {    //如果栈为空,返回 []
            return "[]";
        }

        StringBuilder sb = new StringBuilder();
        sb.append('['); //当栈内不为空时,拼接

        for (int i = 0; i < elementNum; i++) {
            sb.append(element[i]);
            if ((i + 1) == elementNum) {
                return sb.append(']').toString();
            }
            sb.append(',');
        }
        return null;
    }
}
实战应用
实战一:十进制转换二进制

我们都知道,十进制转二进制是将一个数每次都除以2,一直到无法再除以2以后,倒着将每次除以2后获得的余数连接起来,就是正确的二进制数,如下图

在这里插入图片描述

所以,我们可以看到,最先获得的余数是最后才被取走的,这是一个很典型的栈结构的例子。每次除得的余数,就对其进行入栈操作,最后再进行多次出栈操作就可以实现十进制转二进制的功能了。

代码实现
public static String d2b(Integer number) {
    Stack stack = new Stack();
    String result = "";
    while (number > 0) {
        Object push = stack.push(number % 2);
        System.out.println(push);
        number = number / 2;
    }
    while (!stack.empty()) {
        result += Integer.toString((Integer)stack.pop());
    }
    return result;
}
实战二:分隔符匹配

如果我们写的代码中如果多了一个“{”,后者少了一个“}”,或者括号的顺序错乱,都会报错。接下来我们就用栈来模拟这种分隔符匹配。

思路:当读取一段程序时,如果发现它是左分隔符({、[、(),将它压入栈中。当读到一个右分隔符时()、]、}),弹出栈顶元素,并且查看它是否和该右分隔符匹配。如果它们不匹配,则程序报错。如果到最后一直存在着没有被匹配的分隔符,程序也报错。

我们来看下面这个正确的字符串:a{b(c[d]e)f},在栈中的变化过程:

所读字符栈中内容
a
{{
b{
({(
c{(
[{([
d{([
]{(
e{(
){
f{
}
代码实现
public class BrecketChecker {
    private String input;

    public BrecketChecker(String input) {
        this.input = input;
    }

    //检查分隔符匹配的方法
    public String check() {
        if (input.isEmpty()) {	//如果是空字符串直接返回
            return "代码正常";
        }
        
        Stack stack = new Stack();
        char[] chars = input.toCharArray();
        for (int i=0;i<chars.length;i++) {  //遍历数组
            char aChar = chars[i];
            switch (aChar) {
                //如果是左符号则进入栈
                case '(':
                case '[':
                case '{':
                    stack.push(aChar);
                    break;

                //如果是右符号,进行判断
                case ')':
                case ']':
                case '}':
                    if (!stack.isEmpty()) { //栈不为空,三种正确情况
                        char pop = (char) stack.pop();
                        if ((pop == '(' && aChar == ')') ||
                            (pop == '[' && aChar == ']') ||
                            (pop == '{' && aChar == '}')
                        ) {
                            continue;   //进行下次循环
                        }
                        return "代码有误;位置:" + i + ";代码:" + aChar; //不为三种正确情况,出错
                    } else { //栈如果为空,又有右符号,那么是错误的,必须先有左符号
                        return "代码有误;位置:" + i + ";代码:"+aChar;
                    }
                default:
                    break;
            }
        }
        
        if (stack.isEmpty()) {  //遍历结束,如果栈为空那么是正确的;如果不为空,那么有括号没有匹配
            return "代码正常";
        }
        return "代码有误;有括号没有关闭";
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值