数据结构-栈(三)

一、栈的定义

  • 栈(stack)是一种只能在同一端进行插入或删除操作的线性表。
  • 表中允许进行插入、删除操作的一端称为栈顶(top),表的另一端称为栈底(bottom)。
  • 栈的插入操作通常称为进栈或入栈(push),栈的删除操作通常称为退栈或出栈(pop)。

栈的特点

- 后进先出,即后进栈的元素先出栈。
- 每次进栈的元素都作为新栈顶元素,每次出栈的元素只能是当前栈顶元素。
- 栈也称为后进先出表。

二、顺序栈

顺序栈基本算法实现

public class Stack_arr<E> {
    /**
     * 顺序栈的初始容量(常量)
     */
    final int initcapacity = 10;

    /**
     * 存放顺序栈的容量
     */
    private int capacity;

    /**
     * 存放顺序栈中元素
     */
    private E[] data;

    /**
     * 存放栈顶指针
     */
    private int top;

    public Stack_arr() {
        data = (E[]) new Object[initcapacity];
        capacity = initcapacity;
        top = -1;
    }

    /**
     * 改变栈容量
     *
     * @param newcapacity
     */
    private void updatecapacity(int newcapacity) {
        E[] newdata = (E[]) new Object[newcapacity];
        for (int i = 0; i < top; i++)
            newdata[i] = data[i];
        capacity = newcapacity;
        data = newdata;
    }
    //栈的基本运算算法

    /**
     * 进栈
     *
     * @param e
     */
    public void push(E e) {
        top++;
        if (top == capacity) {
            updatecapacity(top + top / 2);
        }
        this.data[top] = e;
    }

    /**
     * 出栈,返回栈顶元素
     */
    public E pop() {
        if (top == -1) {
            return null;
        } else {
            E e = this.data[top];
            top--;
            return e;
        }
    }

    /**
     * 查看栈顶元素,返回当前的栈顶元素
     */
    public E peek() {
        if (top == -1) {
            return null;
        } else {
            return this.data[top];
        }
    }

    /**
     * 判断栈是否为空,若空栈返回真;否则返回假
     */
    public boolean empty() {
        return top == -1;
    }
}

三、链栈

链栈基本算法实现

public class Stack_link<E>{
    private static class Node<E>{
        E item;
        Node<E> next;

        public Node(E item, Node<E> next) {
            this.item = item;
            this.next = next;
        }
    }
    /**
     * 存放栈顶指针
     */
    private Node<E> head;

    public Stack_link() {
        this.head = new Node<>(null,null);
    }

    //栈的基本运算算法
    /**
     * 进栈
     *
     * @param e
     */
    public void push(E e) {
        Node<E> pNode = new Node<>(e,head.next);
        head.next = pNode;
    }

    /**
     * 出栈,返回栈顶元素
     */
    public E pop() {
        if(this.empty()){
            return null;
        }
        E e = head.next.item;
        head.next = head.next.next;
        return e;
    }

    /**
     * 查看栈顶元素,返回当前的栈顶元素
     */
    public E peek() {
        if(this.empty()){
            return null;
        }
        return head.next.item;

    }

    /**
     * 判断栈是否为空,若空栈返回真;否则返回假
     */
    public boolean empty() {
        return head.next == null;
    }
}

四、栈的常见应用

1、括号匹配

设计一个算法利用顺序栈检查用户输入的表达式中括号是否配对(假设表达式中可能含有圆括号、中括号和大括号)。并用相关数据进行测试。

import java.util.Stack;
public class TestStack {
    public static void main(String[] args) {
        String str = "({)}";
        String str1 = "{[()]}";
        String str2 = "[]{}()";
        System.out.println(str+"配对:"+isMatch(str));
        System.out.println(str1+"配对:"+isMatch(str1));
        System.out.println(str2+"配对:"+isMatch(str2));
    }
    
     public static boolean isMatch(String string) {
            Stack<Character>  stack = new Stack<>();
            int i = 0;
            while(i<string.length()) {
                char ch = string.charAt(i);
                if(ch == '{' || ch == '(' ||ch == '[' ) {
                    stack.push(ch);
                }else if (ch == ')') {
                    if(stack.peek() == '(' ) {
                        stack.pop();
                    }
                }else if (ch == '}') {
                    if(stack.peek() == '{' ) {
                        stack.pop();
                    }
                }else if (ch == ']') {
                    if(stack.peek() == '[' ) {
                        stack.pop();
                    }
                }
                i++;
            }
            return stack.empty();
        }
}

2、逆波兰表达式

逆波兰表达式

ps:逆波兰表达式是一种利用栈来进行运算的数学表达式

\[9+(3-1) \ast 3+10 \div 2 \\标准四则运算表达式—中缀表达式\\ 9\,\,3\,\,1-3*+ 10\,\,2/+ \\ 算机采用的—后缀表达式:逆波兰表达式 \]

中缀表达式---> 后缀表达式

import java.util.Stack;

public class TestStack {
    public static void main(String[] args) {
        String exp = "9+(3-1)*3+10/2";
        String convert = convert(exp);
        System.out.println(convert);
    }

    /**
     * 将中缀表达式转换为后缀表达式
     * @param str
     * @return
     */
    public static String convert(String str) {
        Stack<Character> stack = new Stack<>();
        StringBuffer sb = new StringBuffer();
        char ch;
        char e;
        int i = 0;
        while (i < str.length()) {
            ch = str.charAt(i);
            if (ch == '(') {
                stack.push(ch);
            } else if (ch == ')') {
                while (!stack.empty() && stack.peek() != '(') {
                    //所有运算符出栈
                    e = stack.pop();
                    sb.append(e);
                }
                stack.pop();//(出栈
            } else if (ch == '+' || ch == '-') {
                while (!stack.empty() && stack.peek() != '(') {
                    e = stack.pop();
                    sb.append(e);
                }
                stack.push(ch);
            } else if (ch == '*' || ch == '/') {
                while (!stack.empty() && stack.peek() != '('
                        && (stack.peek() == '*' || stack.peek() == '/')) {
                    e = stack.pop();
                    sb.append(e);
                }
                stack.push(ch);
            } else {
                while (ch>='0'&&ch<='9'){
                    sb.append(ch);
                    i++;
                    if(i<str.length()){
                        ch = str.charAt(i);
                    }else{
                        break;
                    }
                }
                i--;
                sb.append("#");
            }
            i++;
        }
        while (!stack.empty()) {
            e = stack.pop();
            sb.append(e);
        }
        return sb.toString();
    }
}

后缀表达式计算

import java.util.Stack;

public class TestStack {
    public static void main(String[] args) {
        String exp = "9+(3-1)*3+10/2";
        String convert = convert(exp);
        System.out.println("后缀表达式:"+convert);
        Double calculate = calculate(convert);
        System.out.println("计算值:"+calculate);
}


    /**
     * 后缀表达式计算
     * @param suffixExp
     * @return
     */
    public static Double calculate(String suffixExp){
        Stack<Double> stack = new Stack<>();
        //操作数1
        Double a;
        //操作数2
        Double b;
        //运算结果
        StringBuffer sb;
        int i = 0;
        while (i<suffixExp.length()){
            char ch = suffixExp.charAt(i);
            if(ch>='0'&&ch<='9'){
                sb = new StringBuffer();
                while (ch>='0'&&ch<='9'){
                    sb.append(ch);
                    i++;
                    ch=suffixExp.charAt(i);
                }
//                System.out.println(sb);
                double v = Double.parseDouble(sb.toString());
                sb = null;
                stack.push(v);
            }else if(ch=='+'){
                b = stack.pop();
                a = stack.pop();
                stack.push(a+b);
            }else if(ch=='-'){
                b = stack.pop();
                a = stack.pop();
                stack.push(a-b);
            }else if(ch == '*'){
                b = stack.pop();
                a = stack.pop();
                stack.push(a*b);
            }else if(ch=='/'){
                b = stack.pop();
                a = stack.pop();
                stack.push(a/b);
            }
            i++;
        }
        return stack.peek();
    }
}

posted @ 2022-07-08 14:37  胡同咖啡  阅读(54)  评论(0编辑  收藏  举报