棧定義
棧(stack):是一種特殊的串列形式的資料結構,其特殊之處在於只允許在連結串列或者陣列的
一端進行插入、刪除操作。其實現方式可以通過一維陣列和連結串列來實現。
Tips:簡單的來說棧其實也是一種操作受限的線性表。是一種後進先出的資料結構可以使用數
組或者鏈表的形式來實現。
棧的動作表現形式:
棧實現
知道了棧的定義,我們來看看棧的實現吧。首先我們需要明白的的是棧具有哪些操作。
通過一個介面定義其操作。
package com.kiritor;/** * 棧操作定義 * @author Kiritor*/public interface Stack<T> { /*判空*/ boolean isEmpty(); /*清空棧*/ void clear(); /*彈棧*/ T pop(); /*入棧*/ boolean push(T data); /*棧的長度*/ int length(); /*查看棧頂的元素,但不移除它*/ T peek(); /*返回對象在棧中的位置*/ int search(T t);}
棧的數組實現
棧的數組實現,底層使用數組
package com.kiritor;/** * 棧的數組實現 * @author Kiritor*/public class ArrayStack<T> implements Stack<T>{private T[] t = (T[]) new Object[16];//棧空間預設為16 private int size = 0;@Overridepublic boolean isEmpty() {return size==0;}@Overridepublic void clear() {for(int i = 0;i<t.length;i++)t[i]=null;//將其引用只為null,方便gc進行回收size = 0;//棧的大小置0}/*彈棧操作*/@Overridepublic T pop() {if(size==0) return null;else{ T tmp = t[size-1]; t[size-1]=null;//便於gc回收 size--; return tmp;}}@Overridepublic boolean push(T data) {if(size>=t.length){//棧空間已滿,需要擴容resize();}t[size++]=data;return true;}public void resize(){T[] tmp = (T[]) new Object[t.length*2];for(int i = 0;i<t.length;i++){tmp[i]=t[i];t[i]=null;//便於gc處理}t = tmp;tmp = null;//便於gc處理,提高程式效率}@Overridepublic int length() {return size;}/*查看棧頂元素,但是並不刪除*/@Overridepublic T peek() {if(size==0) return null;else{ return t[size-1];}} /*下表從1開始*/@Overridepublic int search(T t) {for(int i= 0;i<size;i++)if(t.equals(this.t[i]))return i+1;return 0;}@Overridepublic String toString() { StringBuilder sb = new StringBuilder(); sb.append("ArrayStack:\n[\n"); for (int i = size-1; i >=0; i--) { sb.append(" "+t[i].toString()); if (i != size + 1) { sb.append("\n"); } } sb.append("]"); return sb.toString(); } } 測試代碼:
public static void main(String[] args) { ArrayStack<String> arrayStack = new ArrayStack<>(); arrayStack.push("C語言"); arrayStack.push("C++"); arrayStack.push("JAVA"); arrayStack.push("資料結構"); arrayStack.pop(); arrayStack.peek(); arrayStack.pop(); System.out.println(arrayStack.toString());} 輸出結果:
棧的鏈表實現
package com.kiritor;/** * 棧的鏈表實現 * @author Kiritor*/public class LinkStack<T> implements Stack<T>{/*將資料封裝成結點*/ class Node { private Node pre; private T data; } /*棧頂指標*/ private Node top; private int size;//棧的大小 public LinkStack() {this.top = null;this.size = 0;}@Overridepublic boolean isEmpty() {return size==0;}@Overridepublic void clear() {top = null;size = 0;}@Overridepublic T pop() {if (top != null) { T t = top.data; // 改變棧頂指標 top = top.pre; size--; return t; } return null; }@Overridepublic boolean push(T data) { Node node = new Node(); node.data = data; node.pre = top; // 改變棧頂指標 top = node; size++; return true; }@Overridepublic int length() {return size;}@Overridepublic T peek() {return top.data;} /*下表從1開始*/@Overridepublic int search(T t) {int count=0;for(Node node= top;node.pre!=null;node = node.pre){count++;if(t.equals(node.data)) return size - count;}return 0;}@Overridepublic String toString() { StringBuilder sb = new StringBuilder(); sb.append("LinkStack:"+length()+"\n[\n"); int count=0; for (Node node = top;node!=null;node=node.pre) { count++; sb.append(" "+node.data.toString()); if (count != size + 1) { sb.append("\n"); } } sb.append("]"); System.out.println(count); return sb.toString(); }} 測試代碼:
public static void main(String[] args) { LinkStack<String> arrayStack = new LinkStack<>(); arrayStack.push("C語言"); arrayStack.push("C++"); arrayStack.push("JAVA"); arrayStack.push("資料結構"); System.out.println(arrayStack.toString());} 結果就不貼出了
因為棧操作的特殊性,一般來說以數組方式實現的棧的效率是要高於鏈表實現的,
原因在於:其一數組的訪問更快。其二由於只在棧頂進行操作並未涉及太大的元素移動
但是使用鏈式實現將資料封裝成Node,在從其中取資料,還的維護棧頂指標和前驅指標。