• 日常学习随笔-数组、单链表、双链表三种形式实现栈结构的基本操作(源码+注释)


    一、栈结构

      栈(stack)是限制插入和删除只能在一个位置上的表,该位置是 表的末端,叫做栈的顶(Top)。对栈的基本操作有push(进栈),pop(出栈),peak(栈顶元素),size(栈容量)等。

      栈的核心思想:“先进后出”。

    二、案例一:数组实现“栈”  

      1 package com.xfwl.algorithmAnalysis.stack;
      2 
      3 import java.util.Arrays;
      4 
      5 /**
      6  * 自定义栈结构(基于数组的形式)
      7  * 栈的核心思想:先进后出
      8  * @function  日常学习测试
      9  * @author 小风微凉
     10  * @time  2018-5-19 上午10:19:07
     11  * @param <T>
     12  */
     13 public class MyStackDefin3<T> {
     14     /**
     15      * 定义一个默认扩展容量
     16      */
     17     private static final int DEFAULT_CAPACITY=10;
     18     /**
     19      * 栈-容器数组
     20      */
     21     private T[] stackArr;
     22     /**
     23      * 计数器
     24      */
     25     private int nodeCount=0;
     26     /**
     27      * 设置容器大小
     28      * @param newCapacity 新容量大小
     29      * 说明:这里参考ArrayList源码中的一套扩展规则">>"
     30      */
     31     public void ensureCapacity(int newCapacity){
     32         //大小范围检查
     33         if(newCapacity<=this.size()){//不超过了当前容器的容量大小
     34             return;//则不需要扩展容器容量
     35         }
     36         //数组初始值判断 
     37         if(this.stackArr==null){
     38             stackArr=(T[]) new Object[newCapacity];
     39             return;//第一次初始化进来
     40         }
     41         //需要扩展容器容量
     42         T[] newItems=(T[]) Arrays.copyOf(this.stackArr, newCapacity,this.stackArr.getClass());
     43         this.stackArr=newItems;
     44     }
     45     /**
     46      * 栈构造器
     47      */
     48     public MyStackDefin3(){
     49         //重置栈结构
     50         this.ensureCapacity(DEFAULT_CAPACITY);
     51         nodeCount=0;
     52     }    
     53     /**
     54      * 数据入栈
     55      * @param data
     56      */
     57     public void push(T data){
     58         if(this.size()==this.stackArr.length){//数组容量达到上限
     59             int newCapacity=this.size()+this.size()>>1;//扩展量:取当前容量的一半,且向下取整
     60             this.ensureCapacity(newCapacity);
     61         }
     62         this.stackArr[this.size()]=data;    
     63         this.nodeCount++;
     64     }
     65     /**
     66      * 数据出栈
     67      */
     68     public void pop(){
     69         this.stackArr[this.size()-1]=null;    
     70         this.nodeCount--;        
     71     }
     72     /**
     73      * 返回当前栈中的数据条数
     74      * @return
     75      */
     76     public int size(){
     77         return this.nodeCount;
     78     }
     79     
     80     /**
     81      * 返回栈的最顶端的元素
     82      * @return
     83      */
     84     public T peak(){
     85         return this.stackArr[(this.size()-1)<0?0:this.size()-1];
     86     }
     87     /**
     88      * 打印当前栈信息
     89      */
     90     public void print(){
     91         System.out.println("----------开始打印----------------------");
     92         if(this.size()==0){
     93             System.out.println("空栈,无检索数据!");
     94         }else{            
     95             for(int i=0;i<this.size();i++){
     96                 System.out.println("栈结点数据:"+this.stackArr[i]);                
     97             }
     98         }        
     99         System.out.println("----------打印结束----------------------");
    100     }
    101 }

    测试类:

     1 package com.xfwl.algorithmAnalysis.stack;
     2 /**
     3  * 测试类
     4  * @function  
     5  * @author 小风微凉
     6  * @time  2018-5-19 上午9:43:05
     7  */
     8 public class Test3 {
     9     public static void main(String[] args) {
    10         //创建一个空栈
    11         MyStackDefin3<Object> stack=new MyStackDefin3<>();
    12         stack.print();
    13         System.out.println("当前栈顶数据:"+stack.peak());
    14         //数据入栈
    15         stack.push("第1个数据");
    16         stack.push("第2个数据");
    17         stack.push("第3个数据");
    18         stack.push("第4个数据");
    19         stack.push("第5个数据");
    20         //打印
    21         stack.print();
    22         System.out.println("当前栈顶数据:"+stack.peak());
    23         //数据出栈
    24         stack.pop();
    25         //打印
    26         stack.print();
    27         System.out.println("当前栈顶数据:"+stack.peak());
    28     }
    29 }

    运行结果:

    ----------开始打印----------------------
    空栈,无检索数据!
    ----------打印结束----------------------
    当前栈顶数据:null
    ----------开始打印----------------------
    栈结点数据:第1个数据
    栈结点数据:第2个数据
    栈结点数据:第3个数据
    栈结点数据:第4个数据
    栈结点数据:第5个数据
    ----------打印结束----------------------
    当前栈顶数据:第5个数据
    ----------开始打印----------------------
    栈结点数据:第1个数据
    栈结点数据:第2个数据
    栈结点数据:第3个数据
    栈结点数据:第4个数据
    ----------打印结束----------------------
    当前栈顶数据:第4个数据

    三、案例二:单链表实现“栈” 

      1 package com.xfwl.algorithmAnalysis.stack;
      2 /**
      3  * 自定义栈结构(基于单链表的形式)
      4  * 栈的核心思想:先进后出
      5  * @function  日常学习测试
      6  * @author 小风微凉
      7  * @time  2018-5-18 下午1:49:31
      8  */
      9 public class MyStackDefin<T> {
     10     /**
     11      * 头结点
     12      */
     13     private Node<T> head;
     14     /**
     15      * 计数器
     16      */
     17     private int nodeCount=0;
     18     /**
     19      * 栈构造器
     20      */
     21     public MyStackDefin(){
     22         //重置栈结构
     23         head=new Node(null,null);
     24         nodeCount=0;
     25     }
     26     /**
     27      * 内置一个结点类
     28      */
     29     private class Node<T>{
     30         /**
     31          * 结点数据域
     32          */
     33         private T data;
     34         /**
     35          * 结点指针域
     36          */
     37         private Node<T> next;
     38         /**
     39          * 结点构造函数
     40          */
     41         public Node(T data,Node<T> node){
     42             this.data=data;
     43             this.next=node;
     44         }
     45     }
     46     /**
     47      * 数据入栈
     48      * @param data
     49      */
     50     public void push(T data){
     51         //创建一个结点
     52         Node<T> node=new Node(data,null);
     53         //入栈
     54         this.peakNode().next=node;
     55         this.nodeCount++;
     56     }
     57     /**
     58      * 数据出栈
     59      */
     60     public void pop(){
     61         //找到最后一个结点
     62         Node tmp=this.head;
     63         //判断是否只有一个头结点
     64         if(this.size()==0){
     65             System.out.println("当前栈中无数据,请先让数据入栈!");
     66             return ;
     67         }else{
     68             int count=0;
     69             while(tmp.next!=null){
     70                 if(count==(this.size()-1)){
     71                     break;
     72                 }
     73                 tmp=tmp.next;
     74                 count++;
     75             }
     76             //出栈操作
     77             tmp.next=null;
     78             this.nodeCount--;
     79         }
     80     }
     81     /**
     82      * 返回当前栈中的数据条数
     83      * @return
     84      */
     85     public int size(){
     86         return this.nodeCount;
     87     }
     88     /**
     89      * 返回栈的最顶端的元素结点
     90      * @return
     91      */
     92     public Node<T> peakNode(){
     93         Node<T> tmp=this.head;
     94         while(tmp.next!=null){
     95             tmp=tmp.next;
     96         }
     97         return tmp;
     98     }
     99     /**
    100      * 返回栈的最顶端的元素
    101      * @return
    102      */
    103     public T peak(){
    104         Node<T> tmp=this.head;
    105         while(tmp.next!=null){
    106             tmp=tmp.next;
    107         }
    108         return tmp.data;
    109     }
    110     /**
    111      * 打印当前栈信息
    112      */
    113     public void print(){
    114         System.out.println("----------开始打印----------------------");
    115         if(this.size()==0){
    116             System.out.println("空栈,无检索数据!");
    117         }else{
    118             Node tmp=this.head.next;
    119             for(int i=0;i<this.size();i++){
    120                 System.out.println("栈结点数据:"+tmp.data);
    121                 tmp=tmp.next;
    122             }
    123         }        
    124         System.out.println("----------打印结束----------------------");
    125     }
    126 }

    测试类:

    package com.xfwl.algorithmAnalysis.stack;
    /**
     * 测试类
     * @function  
     * @author 小风微凉
     * @time  2018-5-19 上午9:43:05
     */
    public class Test {
        public static void main(String[] args) {
            //创建一个空栈
            MyStackDefin<Object> stack=new MyStackDefin<>();
            stack.print();
            System.out.println("当前栈顶数据:"+stack.peak());
            //数据入栈
            stack.push("第1个数据");
            stack.push("第2个数据");
            stack.push("第3个数据");
            stack.push("第4个数据");
            stack.push("第5个数据");
            //打印
            stack.print();
            System.out.println("当前栈顶数据:"+stack.peak());
            //数据出栈
            stack.pop();
            //打印
            stack.print();
            System.out.println("当前栈顶数据:"+stack.peak());
        }
    }

    运行结果:

    ----------开始打印----------------------
    空栈,无检索数据!
    ----------打印结束----------------------
    当前栈顶数据:null
    ----------开始打印----------------------
    栈结点数据:第1个数据
    栈结点数据:第2个数据
    栈结点数据:第3个数据
    栈结点数据:第4个数据
    栈结点数据:第5个数据
    ----------打印结束----------------------
    当前栈顶数据:第5个数据
    ----------开始打印----------------------
    栈结点数据:第1个数据
    栈结点数据:第2个数据
    栈结点数据:第3个数据
    栈结点数据:第4个数据
    ----------打印结束----------------------
    当前栈顶数据:第4个数据

    四、案例三:双链表实现“栈” 

      1 package com.xfwl.algorithmAnalysis.stack;
      2 /**
      3  * 自定义栈结构(基于双链表的形式)
      4  * 栈的核心思想:先进后出
      5  * @function  日常学习测试
      6  * @author 小风微凉
      7  * @time  2018-5-19 上午10:00:07
      8  * @param <T>
      9  */
     10 public class MyStackDefin2<T> {
     11     /**
     12      * 头结点
     13      */
     14     private Node<T> head;
     15     /**
     16      * 计数器
     17      */
     18     private int nodeCount=0;
     19     /**
     20      * 栈构造器
     21      */
     22     public MyStackDefin2(){
     23         //重置栈结构
     24         head=new Node(null,null,null);
     25         nodeCount=0;
     26     }
     27     /**
     28      * 内置一个结点类
     29      */
     30     private class Node<T>{
     31         /**
     32          * 结点数据域
     33          */
     34         private T data;
     35         /**
     36          * 结点前驱指针域
     37          */
     38         private Node<T> prev;
     39         /**
     40          * 结点后驱指针域
     41          */
     42         private Node<T> next;
     43         /**
     44          * 结点构造函数
     45          */
     46         public Node(T data,Node<T> prev,Node<T> next){
     47             this.data=data;
     48             this.prev=prev;
     49             this.next=next;
     50         }
     51     }
     52     /**
     53      * 数据入栈
     54      * @param data
     55      */
     56     public void push(T data){
     57         //创建一个结点
     58         Node<T> node=new Node(data,this.peakNode(),null);
     59         //入栈
     60         this.peakNode().next=node;
     61         this.nodeCount++;
     62     }
     63     /**
     64      * 数据出栈
     65      */
     66     public void pop(){
     67         //找到最后一个结点
     68         Node tmp=this.head;
     69         //判断是否只有一个头结点
     70         if(this.size()==0){
     71             System.out.println("当前栈中无数据,请先让数据入栈!");
     72             return ;
     73         }else{
     74             int count=0;
     75             while(tmp.next!=null){
     76                 if(count==(this.size()-1)){
     77                     break;
     78                 }
     79                 tmp=tmp.next;
     80                 count++;
     81             }
     82             //出栈操作
     83             tmp.next=null;
     84             this.nodeCount--;
     85         }
     86     }
     87     /**
     88      * 返回当前栈中的数据条数
     89      * @return
     90      */
     91     public int size(){
     92         return this.nodeCount;
     93     }
     94     /**
     95      * 返回栈的最顶端的元素结点
     96      * @return
     97      */
     98     public Node<T> peakNode(){
     99         Node<T> tmp=this.head;
    100         while(tmp.next!=null){
    101             tmp=tmp.next;
    102         }
    103         return tmp;
    104     }
    105     /**
    106      * 返回栈的最顶端的元素
    107      * @return
    108      */
    109     public T peak(){
    110         Node<T> tmp=this.head;
    111         while(tmp.next!=null){
    112             tmp=tmp.next;
    113         }
    114         return tmp.data;
    115     }
    116     /**
    117      * 打印当前栈信息
    118      */
    119     public void print(){
    120         System.out.println("----------开始打印----------------------");
    121         if(this.size()==0){
    122             System.out.println("空栈,无检索数据!");
    123         }else{
    124             Node tmp=this.head.next;
    125             for(int i=0;i<this.size();i++){
    126                 System.out.println("栈结点数据:"+tmp.data);
    127                 tmp=tmp.next;
    128             }
    129         }        
    130         System.out.println("----------打印结束----------------------");
    131     }
    132 }

    测试类:

    package com.xfwl.algorithmAnalysis.stack;
    /**
     * 测试类
     * @function  
     * @author 小风微凉
     * @time  2018-5-19 上午9:43:05
     */
    public class Test2 {
        public static void main(String[] args) {
            //创建一个空栈
            MyStackDefin2<Object> stack=new MyStackDefin2<>();
            stack.print();
            System.out.println("当前栈顶数据:"+stack.peak());
            //数据入栈
            stack.push("第1个数据");
            stack.push("第2个数据");
            stack.push("第3个数据");
            stack.push("第4个数据");
            stack.push("第5个数据");
            //打印
            stack.print();
            System.out.println("当前栈顶数据:"+stack.peak());
            //数据出栈
            stack.pop();
            //打印
            stack.print();
            System.out.println("当前栈顶数据:"+stack.peak());
        }
    }

    运行结果:

    ----------开始打印----------------------
    空栈,无检索数据!
    ----------打印结束----------------------
    当前栈顶数据:null
    ----------开始打印----------------------
    栈结点数据:第1个数据
    栈结点数据:第2个数据
    栈结点数据:第3个数据
    栈结点数据:第4个数据
    栈结点数据:第5个数据
    ----------打印结束----------------------
    当前栈顶数据:第5个数据
    ----------开始打印----------------------
    栈结点数据:第1个数据
    栈结点数据:第2个数据
    栈结点数据:第3个数据
    栈结点数据:第4个数据
    ----------打印结束----------------------
    当前栈顶数据:第4个数据

    五、总结

      栈本身是一种结构思想的具现,实现的方式不固定,我们可以使用最简单的方式,或者复杂(结构层次复杂)的方式去实现,这都没问题,关键点是理解“栈”的核心思想:“先进后出”,在实际的运用场景中,我们就可以根据实际情况创造+改良来产生一套最佳的“栈”结构。

  • 相关阅读:
    开辟空间以存放一个结构体变量
    用结构体变量的引用作函数参数
    用指向结构体变量的指针作实参
    结构体变量作函数参数
    简单链表
    指向结构体变量的指针的应用
    结构体数组应用举例
    对候选人得票的统计程序
    引用结构体变量中的成员
    对三个变量按由小到大的顺序排序
  • 原文地址:https://www.cnblogs.com/newwind/p/9059634.html
Copyright © 2020-2023  润新知