java数据结构--栈

一.栈的概念

 栈是一种先进后出的线性结构,你可以把它看做为一个弹匣,进栈就是把子弹压入弹匣,出栈就是射击一次,把子弹弹出弹匣,下面我们用java来实现一下栈的结构

二.栈Stack接口

我们定义Stack接口

/**
 * 栈的方法定义
 * @author JJH
 * @param <E>
 */
public interface Stack<E> {

    /**
     * 栈顶入栈一个元素
     * @param value
     */
    boolean push(E value);

    /**
     * 从栈顶弹出一个元素,栈顶减一
     * @return
     */
    E pop();

    /**
     * 只获取栈顶元素的值
     * @return
     */
    E peek();

    /**
     * 判断栈是否为空
     * @return
     */
    boolean isEmpty();

    /**
     * 判断栈是否为满
     * @return
     */
    boolean isFull();

}

 主要方法为入栈,出栈,获取栈顶元素值,判断栈为空,为满

三.单向带哨兵链表实现栈

/**
 * 单向带哨兵链表实现栈
 * @author JJH
 */
public class LinkedListStack<E> implements Stack<E>,Iterable<E>{

    //节点类
    static class Node<E>{
        E value;
        Node<E> next;

        public Node(E value,Node<E> next){
            this.value = value;
            this.next = next;
        }
    }

    /**
     *  栈的总容量
     */
    private int capacity;
    /**
     *     当前栈的元素个数
     */
    private int size;
    /**
     * 头哨兵节点
     */
    private Node<E> head;

    /**
     * 初始化
     * @param capacity
     */
    public LinkedListStack(int capacity){
        this.capacity = capacity;
        this.size = 0;
        this.head = new Node<>(null,null);
    }


    @Override
    public boolean push(E value) {
       if(isFull()){
           return false;
       }
        Node<E> node = new Node<>(value,head.next);
        head.next = node;
        size++;
        return true;
    }

    @Override
    public E pop() {
       if(isEmpty()){
           return null;
       }
       Node<E> first  = head.next;
       head.next = first.next;
       size--;
       return first.value;
    }

    @Override
    public E peek() {
       if(isEmpty()){
           return null;
       }
       return head.next.value;
    }

    @Override
    public boolean isEmpty() {
        return  size == 0;
    }

    @Override
    public boolean isFull() {
        return  size == capacity;
    }



    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            Node<E> p = head.next;

            @Override
            public boolean hasNext() {
                return p!=null;
            }

            @Override
            public E next() {
                E value = p.value;
                p = p.next;
                return value;
            }
        };
    }
}

四.数组带top指针实现栈

 * 数组实现栈
 * 原理:
 *    将数组的尾部作为栈顶,设置一个top栈顶指针
 *    开始时指向索引0,也就是栈底位置,
 *    当进栈时让top加一,出栈时top减一
 * @author JJH
 */
public class ArrayStack<E> implements Stack<E>,Iterable<E>{

    /**
     * 数组
     */
    private E[] array;
    /**
     * 栈顶指针
     */
    private int top;
    /**
     * 栈容量
     */
    private int capacity;


    @SuppressWarnings("all")
    public ArrayStack(int capacity){
        this.capacity = capacity;
        this.array = (E[]) new Object[this.capacity];
        this.top = 0;
    }


    @Override
    public boolean push(E value) {
        if (isFull()) {
            return false;
        }
        array[top++] = value;
        return true;
    }

    @Override
    public E pop() {
        if (isEmpty()) {
            return null;
        }
        return array[--top];
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        return array[top-1];
    }

    @Override
    public boolean isEmpty() {
        return top == 0;
    }

    @Override
    public boolean isFull() {
        return top == capacity;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {

            int p = top;

            @Override
            public boolean hasNext() {
                return p > 0;
            }

            @Override
            public E next() {
                return array[--p];
            }
        };
    }

}

 五.栈的一些习题

(1)有效括号

/**
 * 有效括号
 *  题目描述:
 *   如果字符串为: "[],[()],{()},{[()]}" 这种类型,左右括号对称就是有效括号
 *   如果是:"[[)[]}" 这种就不是有效括号
 *  请判断是否是有效括号
 *
 *  思路:
 *    遍历字符串,当遇到左括号 ( , [ , { 时,就把对应的右括号 ) , ] , } 压入栈中,
 *    然后当碰到右括号时,就把该右括号和栈顶的右括号比较,如果相等,就把
 *    栈顶的右括号弹出,相当于匹配成功一对括号,接着比较下一对,
 *    如果不相等,就表示该字符串不是有效括号,直接返回false
 *
 *    如果最后栈为空,就表示全部匹配完成,该字符串是有效括号
 *
 *
 */
public class L20_usingKuohao {



    private  String str;

    public L20_usingKuohao(String str){
        this.str = str;
    }



    public boolean isUsing(){

        LinkedListStack<Character> stack = new LinkedListStack<>(str.length());

        for (int i = 0; i < str.length() ; i++) {
            char c = str.charAt(i);
            switch (c){
                case '(':
                    stack.push(')');
                    break;
                case '[':
                    stack.push(']');
                    break;
                case '{':
                    stack.push('}');
                    break;
                default:
                    if(stack.peek() == c){
                        stack.pop();
                    }else {
                        return false;
                    }
                    break;
            }
        }

        return stack.isEmpty();
    }
}

 (2)求后缀表达式

/**
 * 后缀表达式
 *
 *  例如: 1,2,*,3  转为 (1+2) * 3
 */
public class L120_lasetExpression {
    
    public int getResult(String str){

        LinkedList<String> stack = new LinkedList<>();

        for (int i = 0; i <str.length() ; i++) {

            char c = str.charAt(i);

            switch (c){
                case '+':
                    Integer b = Integer.parseInt(stack.pop());
                    Integer a = Integer.parseInt(stack.pop());

                    stack.add(String.valueOf(a+b));
                   break;
                case '-':
                    Integer b1 = Integer.parseInt(stack.pop());
                    Integer a1 = Integer.parseInt(stack.pop());

                    stack.add(String.valueOf(a1-b1));
                    break;
                case '*':
                    Integer b2 = Integer.parseInt(stack.pop());
                    Integer a2 = Integer.parseInt(stack.pop());

                    stack.add(String.valueOf(a2*b2));
                    break;
                case '/':
                    Integer b3 = Integer.parseInt(stack.pop());
                    Integer a3 = Integer.parseInt(stack.pop());

                    stack.add(String.valueOf(a3/b3));
                    break;
                default:
                    stack.add(String.valueOf(c));
                    break;
            }
            
        }
        
        return Integer.parseInt(stack.pop());

    }

 (3)中缀表达式转后缀表达式

/**
 * 中缀表达式转后缀表达式
 */
public class InFixToEndFix {

    /**
     * 思路:
     *   1.当字符是非运算符时,直接拼接
     *   2.当是运算符时:
     *       (1)若当前运算符优先级<=栈顶运算符优先级,就将栈中>=它的运算符全部弹出,它再入栈
     *       (2)若当前运算符优先级>栈顶运算符优先级,则将当前运算符压入栈中
     *   3.循环弹出栈中剩余的运算符
     *
     *   带括号:
     *     1.如果碰到 ( 就直接把它压入栈中
     *     2.如果碰到 ) 就一直弹出栈顶,直到弹出 (
     */

    public int proprity(char c){
        switch (c){
            case '*':
            case '/':
                return 2;
            case '+':
            case '-':
                return 1;
            case '(':
                return 0;
            default:
                throw new IllegalArgumentException("运算符不合法"+c);
        }
    }

    public String InfixToEndfix(String str){
        LinkedList<Character> stack = new LinkedList<>();
        StringBuilder sb = new StringBuilder(str.length());
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            switch (c){
                case '+':
                case '-':
                case '*':
                case '/':
                    if(stack.isEmpty()){
                        stack.add(c);
                    }else {
                        if(proprity(c)>proprity(stack.peek())){
                            stack.push(c);
                        }else {
                            while (!stack.isEmpty() && proprity(stack.peek())>=c){
                                sb.append(stack.pop());
                            }
                            stack.push(c);
                        }
                    }
                    break;
                case '(':
                    stack.push(c);
                    break;
                case ')':
                    while (!stack.isEmpty() && stack.peek()!='('){
                        sb.append(stack.pop());
                    }
                    stack.pop();
                    break;
                default:
                    sb.append(c);
                    break;
            }
        }
        while (!stack.isEmpty()){
            sb.append(stack.pop());
        }

        return sb.toString();

    }

 读者可以在此基础上实现其他栈的实现,我们下期再见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值