数据结构和算法(Java版)学习笔记之栈(六)

栈的基本知识和栈的应用举例

(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
对于不同的数据结构有着不同的作用,如:数组、链表、树等都适用于数据库应用,通常用来存储数据或记录;而对于栈和队列来说,由于它们都是受限访问的,所以更加的抽象,通常作为程序员的工具来运用,作为构思算法的辅助工具。

  • 这里的受限是指:数组可通过下标随时存储和访问数据,但栈和队列只能在某种特定情况(出栈或入栈)时可取出或压进一个数据;
  • 栈就是一组记录,表现形式为:先进后出;(重点)
  • 栈的实现受其表现形式的约定,但底层的存储一般采用数组或链接实现;
  • 栈的基本算法
    1.进栈(PUSH)算法
    ①若TOP≥n时,则给出溢出信息,作出错处理(进栈前首先检查栈是否已满,满则溢出;不满则作②);
    ②置TOP=TOP+1(栈指针加1,指向进栈地址);
    ③S(TOP)=X,结束(X为新进栈的元素);
    2.退栈(POP)算法
    ①若TOP≤0,则给出下溢信息,作出错处理(退栈前先检查是否已为空栈, 空则下溢;不空则作②);
    ②X=S(TOP),(退栈后的元素赋给X):
    ③TOP=TOP-1,结束(栈指针减1,指向栈顶)。
  • 代码实现:(以下用java代码简单实现类栈的工作原理)
    创建一个stack类:
/**
 *
 * @author 磊大大
 */
public class StackX {
    private long[] stackArray;
    private int maxSize;
    private int top;
    public StackX(int s){
        maxSize = s;
        stackArray = new long[maxSize];
        top = -1;
    }
    //入栈
    public void push(long j){
        if(!isFull())							//检测是否栈满,满则不能入栈
            stackArray[++top] = j; 		 //此处必须先++,因为top=-1
        else
            System.out.println("Stack is fulling!");
    }
    //出栈
    public long pop(){
        if(!isEmpty())							//检测是否为空,为空则不能出栈
            return stackArray[top--];		//出栈后,栈顶指针需要下移
        else{
            System.out.println("Stack is empty!");
            return 0;
        }  
    }
    //查看栈顶元素
    public long peek(){
        return stackArray[top];
    }
    //判断栈是否为空
    public boolean isEmpty(){
        return top==-1;
    }
    //判断栈是否为满
    public boolean isFull(){
        return top==(maxSize-1);
    }
}

创建一个测试类:



/**
 *
 * @author 磊大大
 */
public class StackApp {
    public static void main(String[] args){
        StackX stackArray = new StackX(5);
        //入栈
        stackArray.push(10);
        stackArray.push(9);
        stackArray.push(8);
        stackArray.push(7);
        //判断是否为满
        System.out.println("stackArray is Full: "+stackArray.isFull());
        stackArray.push(6);
        //判断是否为满
        System.out.println("stackArray is Full: "+stackArray.isFull());
        //已满报错
        stackArray.push(5);
        //出栈
        for(int j =0; j<5; j++){
            System.out.print(" "+stackArray.pop());
        }
        System.out.println();
        //判断是否为空
        System.out.println("stackArray is Empty: "+stackArray.isEmpty());
        //已空报错
        stackArray.pop();
    }
}

栈的应用举例

以下两个实例使用的都是同一个的类,这里直接给出:


package StackExample;

/**
 * 栈应用实例
 * @author 磊大大
 */
public class StackX {
    private char[] stackArray;
    private int maxSize;
    private int top;
    public StackX(int s){
        maxSize = s;
        stackArray = new char[maxSize];
        top = -1;
    }
    //入栈
    public void push(char ch){
        if(!isFull())
            stackArray[++top] = ch;
        else
            System.out.println("Stack is Full");
    }
    //出栈
    public char pop(){
        if(!isEmpty())
            return stackArray[top--];
        else
            System.out.println("Stack is Empty");
            return  's';
    }
    //判断是否为空
    public boolean isEmpty(){
        return top == -1;
    }
    //判断是否为满
    public boolean isFull(){
        return top == (maxSize-1);
    }
}

  1. 实例一:单词的逆序输出(控制台输入,之后逆序输出,用栈实现)
    原理大家应该都清楚,所以直接给出代码实例:

    (一)创建一个反转类:


package StackExample;

/**
 * 单词反转
 * @author 磊大大
 */
public class StackReverser {
    private String input;
    private String output;
    public StackReverser(String in){
        input = in;
    }
    //单词反转函数
    public String doRev(){
        int stackSize = input.length();
        StackX theStack = new StackX(stackSize);
        //单词入栈
        for(int j =0; j<input.length(); j++){
            char ch_in = input.charAt(j);
            theStack.push(ch_in);
        }
        //单词出栈
        output = "";
        while(!theStack.isEmpty()){
            char ch_out = theStack.pop();
            output+=ch_out;
        }
        return output;
    }
    
}

(二)反转实现


package StackExample;
import java.io.*;
/**
 * 单词反转测试,从控制台输入单词
 * @author 磊大大
 */
public class StackReverserApp {
    public static void main(String[] args) throws IOException{
        String input,output;
        while(true){
            System.out.println("Enter a String:");
            System.out.flush();
            input = getString();
            //输入空值结束
            if(input.equals(""))
                break;
            StackReverser theReverser = new StackReverser(input);
            output = theReverser.doRev();
            System.out.println("Before reverser: "+input);
            System.out.println("After reverser: "+output;
        }
    }
    //从控制台输入
    public static String getString() throws IOException{
        InputStreamReader inr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(inr);
        String s = br.readLine();
        return s;
    }
}

这里JDK自带一个反转方法:

 //JDK自带的反转
StringBuilder builder = new StringBuilder(input);
System.out.println("StringBuilder Reverser: "+builder.reverse());

两种方法的结果一致,请自行实现。

  1. 实例二:括号的检测
    在控制台输入一串带有括号的字符,如:a { b [ c ( d ) ] },这里的括号都是成对出现的,括号检测的作用就是检测那个括号不是一对,并提示出来。(有点像我们在编程时,如果少个括号编译不通过,会给出提示,或者和eclipse这些开发软件检测括号是否正确一样);
    原理:对于这样一串字符串进行拆分比对,如果等于“{”、“[”、“(”这三种括号,则进行入栈操作,将它们压入栈中;之后继续检测,如果碰到“}”、“]”、“)”中的其中一个,进行一次出栈,并进行比对,如果能够和出栈的凑成一对“{}”、“[]”、“()”,则说明输入正确,否则就报错。在比对完后需要进行栈是否为空检测,若不为空,说明少输入了一个右括号,否则正确;
  • 代码实现

(一)创建括号检测类:


package StackExample;

/**
 * 利用栈实现括号检查
 * @author 磊大大
 */
public class StackBracket {
    private String input;
    public StackBracket(String in){
        input = in;
    }
    //括号检查
    public void check(){
        int stackSize = input.length();
        StackX theStack = new StackX(stackSize);
        for(int j=0; j<input.length(); j++){
            char ch_in = input.charAt(j);
            switch(ch_in){
                case '{':
                case '[':
                case '(':
                    theStack.push(ch_in);
                    break;
                case '}':
                case ']':
                case ')':
                    if(!theStack.isEmpty()){
                        char ch_out = theStack.pop();
                        if((ch_in == '}' && ch_out!='{') || (ch_in == ']' && ch_out!='[') || (ch_in == ')' && ch_out!='('))
                            System.out.println("Error: "+ch_in+" at "+j);
                    }
                default:
                    break;
            }
        }
        //不为空也出错,说明少一个右括号
        if(!theStack.isEmpty())
            System.out.println("Error: missing right delimiter!");
    }
}

(二)检测实现:


package StackExample;

import java.io.BufferedReader;
import java.io.*;

/**
 * 括号检查代码测试
 * @author 磊大大
 */
public class StackBracketApp {
    public static void main(String[] args) throws IOException{
        String input,output;
        while(true){
            System.out.println("Enter string containing delimiters:");
            System.out.flush();
            input = getString();
            if(input.equals(""))
                break;
            StackBracket theStack = new StackBracket(input);
            theStack.check();
        }
    }
    //从控制台输入
    public static String getString() throws IOException{
        InputStreamReader inr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(inr);
        String s = br.readLine();
        return s;
    }
}

以上就是关于栈的Java实现和应用举例,小伙伴们有没有一种发现了新大陆的感觉?不知道eclipse中的括号检测是不是就是按这样的原则来的呢!
下一篇学习队列的相关知识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值