文章目錄
一、基本含義
參考:https://mp.weixin.qq.com/s/D9_wM42c3Czhg9-NsPFJ8Q
鏈表和數組是線性結構的基礎,棧和隊列是線性結構的應用。
1.1 棧
含義:可以將棧看成一個箱子。
作用:放置數據。
分類:靜態棧(數組實現) + 動態棧(鏈表實現)。
項目 | 含義 |
---|---|
入棧 | 往箱子裏面放東西 |
出棧 | 往箱子裏面取東西 |
棧底 | 箱子的底部 |
棧頂 | 箱子的頂部 |
特性 | 先進後出(LIFO, Last In First Out) |
1.2 隊列
含義:可以將隊列看成小朋友排隊。
作用:放置數據。
分類:靜態隊列(數組實現) + 動態隊列(鏈表實現)。
項目 | 含義 |
---|---|
入隊 | 新的小朋友排隊打飯了 |
出隊 | 小朋友打完飯,走了。 |
隊頭 | 第一個小朋友 |
對尾 | 最後一個小朋友 |
特性 | 先進先出 |
二、代碼實現
2.1 棧
2.1.1 創建節點類與棧類
本處採用鏈表創建動態棧。
Node.java
public class Node {
public int data;//數據域
public Node next;//指針域,指向下一個節點
public Node() {
}
public Node(int data) {
this.data = data;
}
public Node(int data, Node next) {
this.data = data;
this.next = next;
}
}
Stack.java
public class Stack {
public Node stackTop; // 棧頂指針
public Node stackBottom; // 棧底指針
public Stack(Node stackTop, Node stackBottom) {
this.stackTop = stackTop;
this.stackBottom = stackBottom;
}
public Stack() {
}
}
2.1.2 遍歷棧
含義:獲取節點值。
只要棧頂元素的指針不指向棧底,那麼就一直輸出遍歷結果。
public static void traverse(Stack stack) {
Node stackTop = stack.stackTop;
while (stackTop != stack.stackBottom) {
System.out.println("棧元素值:" + stackTop.data);
stackTop = stackTop.next;
}
}
2.1.3 判斷該棧是否爲空
含義:是否有元素。
只要棧頂和棧底是同一指向,那麼該棧就爲空。
public static boolean isEmpty(Stack stack) {
return ((stack.stackTop == stack.stackBottom) ? true:false);
}
2.1.4 入棧(進棧)
含義:增加新節點。
將原本棧頂指向的節點交由新節點來指向,棧頂指向新加入的節點。
public static void pushStack(Stack stack, int value) {
Node newNode = new Node(value); // 新節點
// 交換。
newNode.next = stack.stackTop;// 棧頂本來指向的節點交由新節點來指向
stack.stackTop = newNode;// 棧頂指針指向新節點
}
2.1.5 出棧
含義:刪除元素。
1、在出棧之前看看該棧是否爲空,不爲空纔出棧…
2、將棧頂的元素的指針(指向下一個節點)賦值給棧頂指針(完成出棧)
public static void popStack(Stack stack) {
// 棧不爲空才能出棧
if (!isEmpty(stack)) {
Node top = stack.stackTop;//棧頂元素
stack.stackTop = top.next; // 棧頂指針指向下一個節點
System.out.println("出棧的元素是:" + top.data);
}
}
2.1.6 清空棧
含義:刪除所有元素。
棧頂指向棧底,就清空棧了。
public static void clearStack(Stack stack) {
stack.stackTop = null; // 棧頂置空
stack.stackBottom = stack.stackTop; // 棧底指向棧頂。
}
2.2 隊列
使用數組來實現靜態隊列,往往實現靜態隊列,我們都是做成循環隊列。
做成循環隊列的好處是不浪費內存資源!
注意:
1、初始值,front = 0,rear = 0;
2、非循環隊列時:入隊時,rear++。出隊時,front++。
3、數組長度 >= 隊列長度 + 1
4、循環隊列時:入隊時,(rear+1)% arr.length。出隊時,(front + 1) % arr.length。
2.2.1 創建隊列類
Queue.java
public class Queue {
public int [] arrays; // 數組
public int front; // 指向第一個有效的元素
public int rear; // 指向有效數據的下一個元素(即指向無效的數據)
}
// rear並不指向最後一個有效的元素。目的:讓我們分得清隊頭和隊尾。
2.2.2 初始化隊列
此時隊列爲空,分配了6個長度給數組(只能裝5個實際的數字,rear指向的是無效的位置的)
public static void main(String[] args) {
//初始化隊列
Queue queue = new Queue();
queue.front = 0;
queue.rear = 0;
queue.arrays = new int[6];
}
// 注意:此處數組長度雖然爲6,但只能裝5個實際數字。
// 注意:一般情況下,隊列的長度 != 數組的長度。滿員時,隊列的長度 + 1 = 數組的長度。原因rear指向的是無效的位置的。
2.2.3 遍歷
只要front節點不指向rear節點,那麼就可以一直輸出
public static void traverseQueue(Queue queue) {
int i = queue.front;// front的位置
while (i != queue.rear) {
System.out.println("元素的值" + queue.arrays[i]);
i = (i + 1) % queue.arrays.length;//移動front
}
}
2.2.4 判斷
隊列滿員狀態:如果rear指針和front指針緊挨着,那麼說明隊列就滿了。
隊列爲空狀態:只要rear和front指針指向同一個位置,那該隊列就是空的了
// 隊列是否滿了。
public static boolean isFull(Queue queue) {
boolean result = ((queue.rear + 1) % queue.arrays.length == queue.front)? true:false;
return result;
}
// 隊列是否爲空
public static boolean isEmpty(Queue queue) {
return (queue.rear == queue.front) ? true:false;
}
2.2.4 入隊
1、判斷該隊列是否滿了。
2、入隊的值插入到隊尾中(具體的位置就是rear指針的位置)。
3、rear指針移動,再次指向無效的元素位置。
public static void enQueue(Queue queue,int value) {
// 不是滿的隊列才能入隊
if (!isFull(queue)) {
// 將新的元素插入到隊尾中
queue.arrays[queue.rear] = value;
// rear節點移動到新的無效元素位置上
queue.rear = (queue.rear + 1) % queue.arrays.length;
}
}
2.2.6 出隊
1、判斷該隊列是否爲null
2、如果不爲null,則出隊,只要front指針往後面移就是出隊了!
public static void outQueue(Queue queue) {
if (!isEmpty(queue)) {
int value = queue.arrays[queue.front];
System.out.println("出隊的元素是:" + value);
// front指針往後面移
queue.front = (queue.front + 1) % queue.arrays.length;
}
}