Java 實(shí)現(xiàn)棧的三種方式
棧:LIFO(后進(jìn)先出),自己實(shí)現(xiàn)一個(gè)棧,要求這個(gè)棧具有push()、pop()(返回棧頂元素并出棧)、peek() (返回棧頂元素不出棧)、isEmpty()這些基本的方法。
一、采用數(shù)組實(shí)現(xiàn)棧
提示:每次入棧之前先判斷棧的容量是否夠用,如果不夠用就用Arrays.copyOf()進(jìn)行擴(kuò)容
import java.util.Arrays; /** * 數(shù)組實(shí)現(xiàn)棧 * @param <T> */ class Mystack1<T> { //實(shí)現(xiàn)棧的數(shù)組 private Object[] stack; //數(shù)組大小 private int size; Mystack1() { stack = new Object[10];//初始容量為10 } //判斷是否為空 public boolean isEmpty() { return size == 0; } //返回棧頂元素 public T peek() { T t = null; if (size > 0) t = (T) stack[size - 1]; return t; } public void push(T t) { expandCapacity(size + 1); stack[size] = t; size++; } //出棧 public T pop() { T t = peek(); if (size > 0) { stack[size - 1] = null; size--; } return t; } //擴(kuò)大容量 public void expandCapacity(int size) { int len = stack.length; if (size > len) { size = size * 3 / 2 + 1;//每次擴(kuò)大50% stack = Arrays.copyOf(stack, size); } } } public class ArrayStack { public static void main(String[] args) { Mystack1<String> stack = new Mystack1<>(); System.out.println(stack.peek()); System.out.println(stack.isEmpty()); stack.push("java"); stack.push("is"); stack.push("beautiful"); stack.push("language"); System.out.println(stack.pop()); System.out.println(stack.isEmpty()); System.out.println(stack.peek()); } }
二、采用鏈表實(shí)現(xiàn)棧
/** * 鏈表實(shí)現(xiàn)棧 * * @param <T> */ class Mystack2<T> { //定義鏈表 class Node<T> { private T t; private Node next; } private Node<T> head; //構(gòu)造函數(shù)初始化頭指針 Mystack2() { head = null; } //入棧 public void push(T t) { if (t == null) { throw new NullPointerException("參數(shù)不能為空"); } if (head == null) { head = new Node<T>(); head.t = t; head.next = null; } else { Node<T> temp = head; head = new Node<>(); head.t = t; head.next = temp; } } //出棧 public T pop() { T t = head.t; head = head.next; return t; } //棧頂元素 public T peek() { T t = head.t; return t; } //??? public boolean isEmpty() { if (head == null) return true; else return false; } } public class LinkStack { public static void main(String[] args) { Mystack2 stack = new Mystack2(); System.out.println(stack.isEmpty()); stack.push("Java"); stack.push("is"); stack.push("beautiful"); System.out.println(stack.peek()); System.out.println(stack.peek()); System.out.println(stack.pop()); System.out.println(stack.pop()); System.out.println(stack.isEmpty()); System.out.println(stack.pop()); System.out.println(stack.isEmpty()); } }
三、采用LinkedList實(shí)現(xiàn)棧
push-----addFirst()
pop-------removeFirst()
peek-----getFirst()
isEmpty-isEmpty()
import java.util.LinkedList; /** * LinkedList實(shí)現(xiàn)棧 * * @param <T> */ class ListStack<T> { private LinkedList<T> ll = new LinkedList<>(); //入棧 public void push(T t) { ll.addFirst(t); } //出棧 public T pop() { return ll.removeFirst(); } //棧頂元素 public T peek() { T t = null; //直接取元素會(huì)報(bào)異常,需要先判斷是否為空 if (!ll.isEmpty()) t = ll.getFirst(); return t; } //棧空 public boolean isEmpty() { return ll.isEmpty(); } } public class LinkedListStack { public static void main(String[] args) { ListStack<String> stack = new ListStack(); System.out.println(stack.isEmpty()); System.out.println(stack.peek()); stack.push("java"); stack.push("is"); stack.push("beautiful"); System.out.println(stack.peek()); System.out.println(stack.pop()); System.out.println(stack.isEmpty()); System.out.println(stack.peek()); } }
接著分享java使用兩種方式實(shí)現(xiàn)簡(jiǎn)單棧
兩種棧的不同點(diǎn)
基于數(shù)組實(shí)現(xiàn)的棧需要指定初始容量,棧的大小是有限的(可以利用動(dòng)態(tài)擴(kuò)容改變其大?。?,基于鏈表實(shí)現(xiàn)的棧則是沒有大小限制的。
基于數(shù)組實(shí)現(xiàn)棧
數(shù)組實(shí)現(xiàn)棧的主要方法就是標(biāo)識(shí)棧頂在數(shù)組中的位置,初始化時(shí)可以將棧頂指向?yàn)?1的虛擬位置,元素入棧則棧頂元素加1,出棧則棧頂元素減一,棧的元素容量為棧頂指針當(dāng)前位置加1,且不能超過底層數(shù)組的最大容量。
/** * 以數(shù)組為底層實(shí)現(xiàn)棧 * @param <T> */ public class MyStackOfArray<T> { private Object[] data;//底層數(shù)組 private int maxSize = 0;//棧存儲(chǔ)的最大元素個(gè)數(shù) private int top = -1;//初始時(shí)棧頂指針指向-1 //默認(rèn)初始化容量為10的棧 public MyStackOfArray(){ this(10); } //初始化指定大小的棧 public MyStackOfArray(int initialSize){ if(initialSize >= 0){ this.maxSize = initialSize; data = new Object[initialSize]; top = -1; }else{ throw new RuntimeException("初始化容量不能小于0" + initialSize); } } //入棧,棧頂指針先加一再填入數(shù)據(jù) public boolean push(T element){ if(top == maxSize - 1){ throw new RuntimeException("當(dāng)前棧已滿,無法繼續(xù)添加元素"); }else{ data[++top] = element; return true; } } //查看棧頂元素 public T peek(){ if(top == -1) throw new RuntimeException("棧已空"); return (T) data[top]; } //出棧,先彈出元素再將棧頂指針減一 public T pop(){ if(top == -1) throw new RuntimeException("棧已空"); return (T) data[top--]; } //判斷當(dāng)前棧是否為空,只需判斷棧頂指針是否等于-1即可 public boolean isEmpty(){ return top == -1; } public int search(T element){ int i = top; while (top != -1){ if(peek() != element) top--; else break; } int result = top + 1; top = i; return top; } public static void main(String[] args) { MyStackOfArray<Integer> myStackOfArray = new MyStackOfArray<>(10); for(int i = 0; i < 10; i++){ myStackOfArray.push(i); } System.out.println("測(cè)試是否執(zhí)行"); for(int i = 0; i < 10; i++){ System.out.println(myStackOfArray.pop()); } } }
基于鏈表實(shí)現(xiàn)棧
基于鏈表實(shí)現(xiàn)棧只要注意控制棧頂指針的指向即可。
/** * 鏈表方式實(shí)現(xiàn)棧 * @param <E> */ public class MyStack<E> { /** * 內(nèi)部節(jié)點(diǎn)類 * @param <E> */ private class Node<E>{ E e; Node<E> next; public Node(){} public Node(E e, Node<E> next){ this.e = e; this.next = next; } } private Node<E> top;//棧頂指針 private int size;//棧容量 public MyStack(){ top = null; } //入棧,將新節(jié)點(diǎn)的next指針指向當(dāng)前top指針,隨后將top指針指向新節(jié)點(diǎn) public boolean push(E e){ top = new Node(e, top); size++; return true; } //判斷棧是否為空 public boolean isEmpty(){ return size == 0; } //返回棧頂節(jié)點(diǎn) public Node<E> peek(){ if(isEmpty()) throw new RuntimeException("棧為空"); return top; } //出棧,先利用臨時(shí)節(jié)點(diǎn)保存要彈出的節(jié)點(diǎn)值,再將top指針指向它的下一個(gè)節(jié)點(diǎn),并將彈出的節(jié)點(diǎn)的next指針賦空即可 public Node<E> pop(){ if(isEmpty()) throw new RuntimeException("棧為空"); Node<E> value = top; top = top.next; value.next = null; size--; return value; } //返回當(dāng)前棧的大小 public int length(){ return size; } public static void main(String[] args) { MyStack<Integer> myStack = new MyStack<>(); for(int i = 0; i < 10; i++){ myStack.push(i); } for(int i = 0; i < 10; i++){ System.out.println(myStack.pop().e); } } }
到此這篇關(guān)于Java 實(shí)現(xiàn)棧的三種方式的文章就介紹到這了,更多相關(guān)Java 實(shí)現(xiàn)棧內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解java中jvm虛擬機(jī)棧的作用
- 深入JVM剖析Java的線程堆棧
- Java數(shù)據(jù)結(jié)構(gòu)之棧的線性結(jié)構(gòu)詳解
- java數(shù)據(jù)結(jié)構(gòu)基礎(chǔ):棧
- Java數(shù)組與堆棧相關(guān)知識(shí)總結(jié)
- java中利用棧實(shí)現(xiàn)字符串回文算法
- java括號(hào)匹配算法求解(用棧實(shí)現(xiàn))
- JAVA jvm系列--java內(nèi)存區(qū)域
- JAVA JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)詳解
- Java 內(nèi)存模型(JVM)
- Java的最大棧深度與JVM核心知識(shí)介紹
相關(guān)文章
TF-IDF理解及其Java實(shí)現(xiàn)代碼實(shí)例
這篇文章主要介紹了TF-IDF理解及其Java實(shí)現(xiàn)代碼實(shí)例,簡(jiǎn)單介紹了tfidf算法及其相應(yīng)公式,然后分享了Java實(shí)現(xiàn)代碼,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11SpringBoot如何實(shí)現(xiàn)word文檔轉(zhuǎn)pdf
這篇文章主要介紹了SpringBoot如何實(shí)現(xiàn)word文檔轉(zhuǎn)pdf,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07Java 數(shù)據(jù)庫時(shí)間返回前端顯示錯(cuò)誤(差8個(gè)小時(shí))的解決方法
本文主要介紹了Java 數(shù)據(jù)庫時(shí)間返回前端顯示錯(cuò)誤(差8個(gè)小時(shí))的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08Java軟件生產(chǎn)監(jiān)控工具Btrace使用方法詳解
這篇文章主要介紹了Java軟件生產(chǎn)監(jiān)控工具Btrace使用方法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07Springboot-Starter造輪子之自動(dòng)鎖組件lock-starter實(shí)現(xiàn)
這篇文章主要為大家介紹了Springboot-Starter造輪子之自動(dòng)鎖組件lock-starter實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05Java泛型在集合使用與自定義及繼承上的體現(xiàn)和通配符的使用
泛型又稱參數(shù)化類型,是Jdk5.0 出現(xiàn)的新特性,解決數(shù)據(jù)類型的安全性問題,在類聲明或?qū)嵗瘯r(shí)只要指定好需要的具體的類型即可。Java泛型可以保證如果程序在編譯時(shí)沒有發(fā)出警告,運(yùn)行時(shí)就不會(huì)產(chǎn)生ClassCastException異常。同時(shí),代碼更加簡(jiǎn)潔、健壯2021-09-09SpringBoot實(shí)現(xiàn)PPT格式文件上傳并在線預(yù)覽功能
本文介紹SpringBoot實(shí)現(xiàn)PPT格式文件上傳并在線預(yù)覽功能,通過上傳接口,可在C盤的tempfile目錄下找到上傳的文件,預(yù)覽時(shí)會(huì)在同級(jí)目錄下創(chuàng)建一個(gè)相同文件名后綴為pdf的文件,每次預(yù)覽會(huì)先查找文件是否存在,存在則直接預(yù)覽,不存在則會(huì)走上面的處理,需要的朋友可以參考下2022-02-02