关于JAVA数据结构_栈(栈的顺序和链式实现)

2.1 栈
2.1.1站的特点及抽象数据类型
栈(Stack),也称堆栈,是一种操作受限的线性表,栈只允许在线性表的一端插入/删除等操作,不允许在其他位置插入/删除
在线性表中进行插入/删除的一端称为栈顶(top),栈顶保存的元素称为栈顶元素,相对的另一端称为栈低(bottom)
如果栈中没有元素称为空栈
向栈中插入元素,称为进栈或入栈,从栈中删除称为退栈或出栈

栈的插入/删除操作只允许在栈顶进行,后进栈必定先出栈,称为后进先出表(First lastOut 简称:Flos)

堆栈抽象数据类型的定义

ADT Stack{
数据对象:D={a0,a1..an, ai是同一种数据类型的元素 }
数据关系:R={<ai,ai+1>}
基本操作:{
      getSize() 返回元素的个数
      isEmpty() 判断堆栈是否为空
      push(Object) 压栈,入栈
      pop() 弹栈,出栈
      peek() 返回栈顶元素

       }ADTStack

  }
2.1.2栈的顺序实现
通过数组存储堆栈的元素
堆栈的操作都在栈顶完成

 1 package demo2;
 2 /**
 3  * 定义接口,定义栈的操作
 4  * @author ASUS
 5  *
 6  */
 7 public interface MyStack {
 8     int getSize();  //返回元素的个数
 9     boolean isEmpty(); //判断堆栈是否为空
10     void push(Object e);  //压栈,入栈
11     Object pop();        //弹栈,出栈
12     Object peek();      //返回栈顶元素    
13 
14 }
 1 package demo2;
 2 
 3 /**
 4  * 堆栈的顺序实现 数组
 5  * @author ASUS
 6  *
 7  */
 8 public class MyArrayStack implements MyStack {
 9     private Object[]elements; //定义数组保存堆栈的元素
10     private static final int DEFAULT_CAPACITY=16; 
11     private int top;  //栈顶指针
12     //在无参构造中.对数组默认初始化
13     public MyArrayStack() {
14         elements=new Object[DEFAULT_CAPACITY];
15     }
16     //在构造方法中,指定堆栈的初始化大小
17     private void MyArrayStack(int initialCapacity) {
18         elements=new Object[initialCapacity];
19     }
20     //返回元素的个数
21     @Override
22     public int getSize() {
23 
24         return top;
25     }
26     //判断堆栈是否为空
27     @Override
28     public boolean isEmpty() {
29 
30         return top<=0;
31     }
32     //入栈/压栈  添加一个元素
33     @Override
34     public void push(Object e) {
35         //判断堆栈是否已满,如果堆栈已满,数组需要扩容
36         if(top>=elements.length){
37             //定义新的数组,默认按两倍扩容
38             Object[] newDate=new Object[elements.length*2];
39             
40             //把原来数组的内容复制到数组中
41             for(int i=0;i<elements.length;i++){
42                 newDate[i]=elements[i];
43             }
44             //让原来的数组名指向新的数组
45             elements=newDate;
46         }
47           //把元素存储到栈顶指针指向的位置
48         elements[top]=e;
49         //栈顶指针上移
50         top++;
51     }
52 
53     //出栈,
54     @Override
55     public Object pop() {
56         //判断堆栈是否为空
57         if(top<=0){
58             throw new StackOverflowError("栈以空");
59         }
60         top--;
61         return elements[top];
62     }
63 
64     //返回栈顶元素,不删除
65     @Override
66     public Object peek() {
67         //判断堆栈是否为空
68                 if(top<=0){
69                     throw new StackOverflowError("栈以空");
70                 }
71         return elements[top-1];
72     }
73     //重写toString方法
74     @Override
75     public String toString() {
76         
77         StringBuilder sb=new StringBuilder();
78         sb.append("[");
79         //从栈顶到栈低
80         for(int i=top-1;i>=0;i--){
81             sb.append(elements[i]);
82             if(i>0){
83                 sb.append(",");
84             }
85             
86         }
87         //
88         sb.append("]");
89         return sb.toString();
90     }
91 
92 }
 1 package demo2;
 2 
 3 public class MyStackTest {
 4 
 5     public static void main(String[] args) {
 6         //创建堆栈
 7         MyArrayStack stack=new MyArrayStack();
 8         System.out.println(stack.isEmpty());  //true
 9         System.out.println(stack.getSize());  //0
10         //压栈
11         stack.push("aa");
12         stack.push("bb");
13         stack.push("cc") ;
14         stack.push("dd");
15         System.out.println(stack.isEmpty());  //false
16         System.out.println(stack.getSize());  //4
17         System.out.println(stack);
18         System.out.println("----------------");
19         //弹栈顶
20         System.out.println(stack.peek());
21         //出栈
22         System.out.println(stack.pop());
23         System.out.println(stack);
24     }
25 
26 }

运行截图:

 

 


2.1.3栈的链式实现
使用链表作为栈的存储结构,有时也称为链栈
栈只允许在线性表的一端进行操作,

 1 package demo2;
 2 
 3 import java.nio.Buffer;
 4 
 5 public class MyLinkStack implements MyStack{
 6     private Node top;
 7     private int size;
 8     @Override
 9     //返回堆栈个数
10     public int getSize() {
11         
12         return size;
13     }
14 
15     //是否为空
16     @Override
17     public boolean isEmpty() {
18         
19         return size==0;
20     }
21 
22     //压栈
23     @Override
24     public void push(Object e) {
25         //根据元素生成结点
26         Node pNode=new Node(e,top);
27         //修改top栈顶指向新的结点
28         top=pNode;
29         size++;
30     }
31 
32     //出栈
33     @Override
34     public Object pop() {
35     //判断堆栈是否为空
36         if(size<1){
37             throw new StackOverflowError("栈为空");
38             }
39         Object oldDate=top.data;
40         top=top.next;
41         size--;
42         return oldDate;
43     }
44 
45     //返回栈顶元素
46     @Override
47     public Object peek(){
48         //判断堆栈是否为空
49                 if(size<1){
50                     throw new StackOverflowError("栈为空");
51                     }
52         
53         return top.data;
54     }
55     @Override
56     public String toString() {
57         StringBuilder sb=new StringBuilder();
58         sb.append("[");
59         for(Node pNode=top;pNode!=null;pNode=pNode.next){
60 
61         
62             sb.append(pNode.data);
63         if(pNode.next!=null){
64             sb.append(",");
65         }
66         }
67             sb.append("]");
68         
69         return sb.toString();
70     }
71     //定义一个内部类,描述链表的结点
72     private class Node{
73         Object data;
74         Node next;
75         public Node(Object data, Node next) {
76             super();
77             this.data = data;
78             this.next = next;
79         }
80         
81         
82     }
83 
84 }
 1 package demo2;
 2 
 3 public class MyLinkStackTest {
 4 
 5     public static void main(String[] args) {
 6         MyLinkStack stack= new MyLinkStack();
 7         System.out.println(stack.isEmpty());
 8         System.out.println(stack.getSize());
 9         //压栈
10         stack.push("aaa");
11         stack.push("bbb");
12         stack.push("ccc");
13         stack.push("ddd");
14         System.out.println(stack);
15         System.out.println("-----------------");
16         
17         //出栈
18         System.out.println(stack.peek());
19         System.out.println(stack);
20     }
21 
22 }

 

 


2.1.3 简单案例
   1.进制转化

package demo3;

import demo2.MyArrayStack;

/**
 * 使用栈完成进制转化
 * @author ASUS
 *
 */
public class TestBaseConversion {

    public static void main(String[] args) {
    /**
     * 把一个十进制num转化为deciml指定的字符串
     * num 接受十进制的字符串
     * decimal 返回num这个整数对应的decimal进制的字符串    
     */
        System.out.println(convert(100, 2));
        
    }
    public static  String convert(int  num ,int  decimal){
        MyArrayStack stack=new MyArrayStack();
        int remainder = num%decimal; //余数
        while (num!=0){
            stack.push(remainder);//余数
            num=num/decimal;
            remainder=num%decimal;
            
        }
        //出栈,余数倒叙
        StringBuilder sb=new StringBuilder();
        while(!stack.isEmpty()){
            sb.append(stack.pop());
        }
        return sb.toString();
        
    }
    

}

 

 

   2.监测表达式中括弧是否匹配

 

 

 1 package demo3;
 2 
 3 import demo2.MyArrayStack;
 4 
 5 
 6 /**
 7  * 监测表达式的括弧是否匹配
 8  * @author ASUS
 9  *
10  */
11 public class TestBracketMatch {
12 
13     public static void main(String[] args) {
14         //测试
15         System.out.println(bracketMatch("(({{}}"));
16         System.out.println(bracketMatch("(({{}}))"));
17         
18     }
19     
20     
21     //检测expression表达式的括弧是否匹配
22     public static boolean bracketMatch(String expression){
23         MyArrayStack stack = new MyArrayStack();
24         //遍历整个表达式,如果是左括弧就入栈,如果是右括弧,就出栈判断是否匹配
25         for(int i=0;i<expression.length();i++){
26             //取出表达式的每个字符
27             char cc=expression.charAt(i);
28             switch (cc) {
29             case '(':
30             case '[':
31             case '{':
32                 stack.push(cc);  //左括弧入栈,Java可以自动装箱与拆箱
33                 break;
34             case '}':
35                 if(!stack.isEmpty()&&stack.pop().equals('{')){
36                     break;
37                 }else{
38                     return false;
39                 }
40             case ']':
41                 if(!stack.isEmpty()&&stack.pop().equals('[')){
42                     break;
43                 }else{
44                     return false;
45                 }
46             case ')':
47                 if(!stack.isEmpty()&&stack.pop().equals('(')){
48                     break;
49                 }else{
50                     return false;
51                 }
52         
53             }
54             
55         }
56         //如果遍历完后,栈为空,表示括弧匹配
57         if(stack.isEmpty()){
58             return true;
59         }else{
60             return false;
61         }
62     }
63 }

 

 

 

 


   3.算法表达式求值
            思路:1.定义两个栈,一个存储操作符operator ,一个存储 operand
                     2.读取表达式,如果操作数就存到operand操作数 栈
                      (1).操作符栈为空,直接入栈
                      (2).吧操作符栈中的的栈顶操作与 当前操作操 作符进行比较
                                 当前操作符优先级高,操作符入栈
                                 当前操作符优先级低(栈顶操作优先级高,), 弹出栈顶操作符,从操作符中弹 出两个操作数进行运算,把运算 符存储到操作数栈,判断当前                                   操作符 =与栈顶操作符之间的关系

 

  1 package demo3;
  2 import demo2.MyArrayStack;
  3 
  4 /**
  5  * 使用栈来计算算出表达式的值
  6  * @author ASUS
  7  *
  8  */  
  9 public class TestCalculateExpression {
 10 
 11     public static void main(String[] args) {
 12         String expression="4+3+(6-10+2*3)*4";
 13         double result=calculate(expression);
 14         System.out.println(result);
 15         
 16     }
 17     //定义方法计算指定次表达式的值
 18     private static double calculate(String expression) {
 19         MyArrayStack operatorStack=new MyArrayStack();
 20         MyArrayStack operandStack=new MyArrayStack();
 21         //遍历表达式的操作数与操作符
 22         for(int i=0;i<expression.length();i++){
 23             char cc = expression.charAt(i);
 24             //如果cc是数字
 25             if(Character.isDigit(cc)){
 26                 //取出操作数
 27                 StringBuilder sb=new StringBuilder();
 28                 //只有是数字就是循环的一部分
 29                 while(Character.isDigit(cc)){
 30                     sb.append(cc);
 31                     i++;
 32                     if(i>=expression.length()){
 33                         break;
 34                     }
 35                     cc=expression.charAt(i);
 36                 }
 37                 //操作数入栈
 38                 operandStack.push(i);
 39                 //修正i变量的值
 40                 i--;
 41             }else{
 42                 //如果是操作符
 43                 //栈为空,直接把操作符入栈
 44                 if(operatorStack.isEmpty()){
 45                     operatorStack.push(cc);
 46                     continue;
 47                 }
 48                 while(!operatorStack.isEmpty()){
 49                     char op1=(char) operatorStack.peek();
 50                 
 51                 //操作符栈不为空的情况
 52                 if(compareOperator(op1,cc)<0){
 53                     //当前运算符优先级高于栈顶运算符优先级
 54                     operatorStack.push(cc);
 55                     break;
 56                 }else if(compareOperator(op1,cc)==0){
 57                     //当前运算符优先级等于栈顶运算符的优先级,只有一种情况,左边小括号遇到右边小括号
 58                     operatorStack.pop();
 59                     break;
 60                 }else{
 61                     //栈顶运算优先级高
 62                     //取出两个操作数
 63                     if(operandStack.isEmpty()){
 64                         throw new RuntimeException( "表达式错误");
 65                     }
 66                     double num1=Double.parseDouble(operandStack.pop().toString());
 67                     if(operandStack.isEmpty()){
 68                         throw new RuntimeException( "表达式错误");
 69                     }
 70                     double num2=Double.parseDouble(operandStack.pop().toString());
 71                     //取栈顶运算符
 72                     char operator=(char) operatorStack.pop();
 73                     //计算num1和num2的值
 74                     double result=compute(operator,num2,num1);
 75                     //把结果存储到操作栈中
 76                     operandStack.push(result);
 77                     //如果栈为空,新的操作符入栈
 78                     if(operatorStack.isEmpty()){
 79                         operatorStack.push(cc);
 80                         break;
 81                     }
 82                 }
 83                 
 84             }
 85         }
 86         }
 87         //当表达式遍历完后,如果操作字符串不为空,需继续计算
 88         while(!operatorStack.isEmpty()){
 89             if(operandStack.isEmpty()){
 90                 throw new RuntimeException( "表达式错误");
 91             }
 92             char operator=(char) operatorStack.pop();
 93             double num1=Double.parseDouble(operandStack.pop().toString());
 94             if(operandStack.isEmpty()){
 95                 throw new RuntimeException( "表达式错误");
 96             }
 97             double num2=Double.parseDouble(operandStack.pop().toString());
 98             if(operandStack.isEmpty()){
 99                 throw new RuntimeException( "表达式错误");
100             }
101             double result=compute(operator,num2,num1);
102             operandStack.push(result);
103         }
104         //当操作栈为空,操作数多余一个数表达式错误
105         if(operandStack.getSize()>1){
106             throw new RuntimeException( "表达式错误");
107         }
108         return  Double.parseDouble(operandStack.pop().toString());
109     }
110     private static double compute(char operator, double num1, double num2) {
111         switch (operator) {
112         case '+':
113             
114             return num1+num2;
115         case '-':
116             
117             return num1-num2;
118         case '*':
119             
120             return num1*num2;
121         case '/':
122     
123         return num1/num2;
124         
125         }
126         return 0;
127     }
128     private static int compareOperator(char op1, char op2) {
129         if(op1=='+'||op1=='-'){
130             if(op2=='*'||op2=='/'||op2=='('){
131                 return -1;
132             }
133         }
134         if(op1=='*'||op1=='/'){
135             if(op2=='('){
136                 return -1;
137             }
138         }
139         if(op1=='('){
140             if(op2==')'){
141                 return 0;
142             }else{
143                 return -1;
144             }
145         }
146         return 1;
147     }
148 
149 }

 

posted @ 2020-10-05 21:33    阅读(409)  评论(0编辑  收藏  举报