1. 程式人生 > >日常學習隨筆-數組、單鏈表、雙鏈表三種形式實現棧結構的基本操作

日常學習隨筆-數組、單鏈表、雙鏈表三種形式實現棧結構的基本操作

ext return lse efi CA 需要 kde 當前 default

一、棧結構

  棧(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個數據

五、總結

  棧本身是一種結構思想的具現,實現的方式不固定,我們可以使用最簡單的方式,或者復雜(結構層次復雜)的方式去實現,這都沒問題,關鍵點是理解“棧”的核心思想:“先進後出”,在實際的運用場景中,我們就可以根據實際情況創造+改良來產生一套最佳的“棧”結構。

日常學習隨筆-數組、單鏈表、雙鏈表三種形式實現棧結構的基本操作