• 关于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 }
  • 相关阅读:
    《设计原本》读书笔记01
    SQL SERVER存储过程的几种示例
    SQLSERVER2008 存储过程基本语法
    (转)C#程序开发中经常遇到的10条实用的代码
    (转)C#正则表达式Regex类的用法
    常用正则表达式
    (转)通过WMI获取网卡MAC地址、硬盘序列号、主板序列号、CPU ID、BIOS序列号
    checkbox:全选与反全选
    checkbox:获取所有已选中的值
    Quartz(任务调度)- Cron
  • 原文地址:https://www.cnblogs.com/yumu77/p/13771702.html
Copyright © 2020-2023  润新知