Java棧和基礎(chǔ)隊列的實現(xiàn)詳解
棧和隊列:都是線性表,都是基于List基礎(chǔ)上的實現(xiàn)
線性表:數(shù)組,鏈表,字符串,棧,隊列
元素按照一條“直線”排列,線性表這個結(jié)構(gòu)中,一次添加單個元素
棧(stack)
一種特殊的線性表,其只允許在固定的一端進行插入和刪除元素操作。進行數(shù)據(jù)插入和刪除操作的一端稱為棧頂,另一端稱為棧底。棧中的數(shù)據(jù)元素遵守后進先出LIFO(Last In First Out)的原則。


棧支持的三個核心操作:
- 入棧push
- 出棧pop
- 返回棧頂元素peek
棧的常見實際應(yīng)用:
- 無處不在的撤銷操作undo,一般任意的編輯器都使用 ctrl + z 操作,其實本質(zhì)就是每次操作一次 ctrl + z 就是一次棧的pop
- 瀏覽器的前進后退,瀏覽器維護了一個棧結(jié)構(gòu)A->B->C,此時頁面停留在C,想要回到頁面B,點擊后退鍵頭就相當(dāng)于將C出棧,此時的棧頂就是B
- 在開發(fā)程序中的“調(diào)用棧”操作系統(tǒng)棧底層就是棧的實現(xiàn)


棧的實現(xiàn)
棧是一種線性表,所以實現(xiàn)它即可使用數(shù)組,也可以使用鏈表
- 基于數(shù)組實現(xiàn)的棧—順序棧(棧頂實際就是數(shù)組尾部,在數(shù)組尾部添加和刪除)
- 基于鏈表實現(xiàn)的棧—鏈式棧(鏈表的頭插和尾插)
在數(shù)組尾部進行刪除和插入的時間復(fù)雜度為O(1),所以用數(shù)組實現(xiàn)棧是我們的首選
實現(xiàn)代碼:
//基于數(shù)組實現(xiàn)的棧
public class MyStack<E> {
private int size;//數(shù)組長度
//實際存儲數(shù)據(jù)的動態(tài)數(shù)組
private List<E> data = new ArrayList<>();
//入棧,默認尾插
public void push(E val){
data.add(val);
size ++;
}
//彈出棧頂元素,返回棧頂?shù)闹?
public E pop(){
if(isEmpty()){
//棧為空
throw new NoSuchElementException("stack is empty!cannot pop!");
}
//刪元素
E val = data.remove(size-1);
size--;
return val;
//上面三句等同于return data.remove(size-1);
}
//返回棧頂元素,但不出棧
public E peek(){
if(isEmpty()){
throw new NoSuchElementException("stack is empty!cannot peek");
}
return data.get(size-1);
}
// 判斷當(dāng)前棧是否為空
public boolean isEmpty() {
return size == 0;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < size; i++) {
sb.append(data.get(i));
if (i != size - 1) {
// 此時還沒到棧頂,還沒到數(shù)組末尾
sb.append(", ");
}
}
sb.append("] top");
return sb.toString();
}
}
//--------------------------
//測試類·
public class StackTest {
public static void main(String[] args) {
MyStack<Integer> myStack = new MyStack<>();
myStack.push(1);
myStack.push(3);
myStack.push(5);
System.out.println(myStack);
System.out.println(myStack.pop());//刪除棧頂
System.out.println(myStack.peek());//輸出棧頂,此時棧頂為3
System.out.println(myStack.isEmpty());
}
}
//輸出結(jié)果:
[1, 3, 5] top
5
3
false
隊列
只允許在一端進行插入數(shù)據(jù)操作,在另一端進行刪除數(shù)據(jù)操作的特殊線性表,隊列遵循先進先出FIFO(First In First Out)的原則 :進行插入操作的一端稱為隊尾(Tail/Rear) 出隊列:進行刪除操作的一端稱為隊頭
其實隊列的定義很簡單,就相當(dāng)于我們現(xiàn)實生活的排隊購物,先排隊的人先結(jié)賬,也就先離開
隊列的子類比棧要復(fù)雜一些,它有:
- 基礎(chǔ)隊列—FIFO
- 基于優(yōu)先級的隊列—按照優(yōu)先級大小出隊
- 循環(huán)隊列—基于數(shù)組實現(xiàn)的
- 雙端隊列
無論是哪種隊列,都必須支持三個核心操作:
- 入隊—offer
- 出隊—poll
- 返回隊首元素—peek
基礎(chǔ)隊列的實現(xiàn)
- 基于數(shù)組實現(xiàn)的隊列—順序隊列
- 基于鏈表實現(xiàn)的隊列—鏈式隊列
由于隊列是從隊尾插入,隊首出隊,而在數(shù)組頭部刪除的時間復(fù)雜度為O(n),此時我們用鏈表會更好一些。而且無論實現(xiàn)哪種隊列都需要覆寫三個基本操作,因此我們將隊列設(shè)計為接口
實現(xiàn)代碼:
public interface Queue<E> {
// 入隊
void offer(E val);
// 出隊
E poll();
// 返回隊首元素
E peek();
// 判斷隊列是否為空
boolean isEmpty();
}
//基于鏈表實現(xiàn)的基礎(chǔ)隊列
public class MyQueue<E> implements Queue<E> {
// 鏈表的每個節(jié)點
// ------------------------------
//內(nèi)部類
private class Node {
E val;
Node next;
public Node(E val) {
this.val = val;
}
}
// ------------------------------
// 當(dāng)前隊列中的元素個數(shù)
private int size;
// 隊首
private Node head;
// 隊尾
private Node tail;
@Override
public void offer(E val) {
Node node = new Node(val);
if (head == null) {
// 此時鏈表為空
head = tail = node;
}else {
tail.next = node;
tail = node;
}
size ++;
}
@Override
public E poll() {
if (isEmpty()) {
throw new NoSuchElementException("queue is empty!cannot poll!");
}
E val = head.val;
Node node = head;
head = head.next;
// 將原來頭節(jié)點脫鉤
node.next = null;
size --;
return val;
}
@Override
public E peek() {
if (isEmpty()) {
throw new NoSuchElementException("queue is empty!cannot peek!");
}
return head.val;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("front [");
// 鏈表的遍歷
for (Node x = head;x != null;x = x.next) {
sb.append(x.val);
if (x.next != null) {
// 還沒走到鏈表尾部
sb.append(", ");
}
}
sb.append("]");
return sb.toString();
}
}
//測試類
public class QueueTest {
public static void main(String[] args) {
Queue<Integer> queue = new MyQueue<>();
queue.offer(1);
queue.offer(3);
queue.offer(5);
System.out.println(queue);
}
}作為初學(xué)者,我們不能小瞧任何簡單的數(shù)據(jù)結(jié)構(gòu)與算法,基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)往往作為高階數(shù)據(jù)結(jié)構(gòu)的一部分來應(yīng)用,萬丈高樓平地起,平時要多加練習(xí),我們一起加油!
到此這篇關(guān)于Java棧和基礎(chǔ)隊列的實現(xiàn)詳解的文章就介紹到這了,更多相關(guān)Java 棧和基礎(chǔ)隊列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java 數(shù)據(jù)結(jié)構(gòu)之棧與隊列
- java 數(shù)據(jù)結(jié)構(gòu)中棧和隊列的實例詳解
- Java深入了解數(shù)據(jù)結(jié)構(gòu)之棧與隊列的詳解
- Java 棧和隊列的相互轉(zhuǎn)換詳解
- 一起來學(xué)習(xí)Java的棧和隊列
- Java?棧與隊列實戰(zhàn)真題訓(xùn)練
- Java 棧與隊列超詳細分析講解
- Java使用跳轉(zhuǎn)結(jié)構(gòu)實現(xiàn)隊列和棧流程詳解
- Java線性結(jié)構(gòu)中棧、隊列和串的基本概念和特點詳解
- Java常見的數(shù)據(jù)結(jié)構(gòu)之棧和隊列詳解
- Java 棧和隊列的交互實現(xiàn)
相關(guān)文章
Java 重寫時應(yīng)當(dāng)遵守的 11 條規(guī)則
這篇文章主要介紹了Java 重寫時應(yīng)當(dāng)遵守的 11 條規(guī)則,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03
SpringBoot + WebSocket 實現(xiàn)答題對戰(zhàn)匹配機制案例詳解
這篇文章主要介紹了SpringBoot + WebSocket 實現(xiàn)答題對戰(zhàn)匹配機制,分別為每個用戶擬定四種在線狀態(tài),通過流程圖給大家展示,需要的朋友可以參考下2021-05-05
一篇文章教你如何在SpringCloud項目中使用OpenFeign
這篇文章主要介紹了SpringCloud 使用Open feign 優(yōu)化詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-08-08

