日常學習隨筆-數組、單鏈表、雙鏈表三種形式實現棧結構的基本操作
阿新 • • 發佈:2018-05-19
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個數據
五、總結
棧本身是一種結構思想的具現,實現的方式不固定,我們可以使用最簡單的方式,或者復雜(結構層次復雜)的方式去實現,這都沒問題,關鍵點是理解“棧”的核心思想:“先進後出”,在實際的運用場景中,我們就可以根據實際情況創造+改良來產生一套最佳的“棧”結構。
日常學習隨筆-數組、單鏈表、雙鏈表三種形式實現棧結構的基本操作