淺談棧和隊列


棧模型

棧(stack)是限制對元素的插入(push)和刪除(pop)只能在一個位置上進行的表,該位置是表的末端,叫做棧的棧頂(top)。

棧的基本操作只有兩種,壓入棧(push)和彈出棧頂(pop),且只能作用於棧頂。(只有棧頂元素是可訪問的

你可以把棧結構理解成一個底部封閉,頂部打開的桶。最先進去的元素一定是最后才能取出,最晚進去的元素一定是最先取出。
因此棧又叫做LIFO(后進先出,Last In First Out)表。

棧的優勢

棧的操作是常數時間的,而且是以非常快的常數時間。在某些機器上,push和pop都可以寫成一條機器指令,現代計算機把棧操作作為它指令的一部分。因此棧是在計算機科學中繼數組之后最基本的數據結構。

棧的實現

棧的實現分為數組實現和鏈表實現。

  1. 鏈表實現
    這里我們使用單鏈表來實現,定義一個first指針指向棧頂,棧的鏈表實現實際上是簡化了單鏈表實現,具體實現看以下代碼。
 1public class StackImplementByLinklist<AnyType> {
2    public Node<AnyType> first;
3    int size;
4    //內部類定義node
5    public class Node<AnyType>{
6        AnyType data;
7        Node<AnyType> next;
8    }
9     //初始化
10    public void stack(){
11        first=null;
12        size=0;
13    }
14
15    public void push(AnyType a){
16        Node oldNode=first;
17        first=new Node();
18        first.data=a;
19        first.next=oldNode;
20        size++;
21    }
22
23    public AnyType pop(){
24        AnyType a=first.data;
25        first=first.next;
26        size--;
27        return a;
28    }
29
30    public boolean isEmpty(){
31        return size==0;
32    }
33
34    public int size(){
35        return size;
36    }
37}
  1. 數組實現
    相比於鏈表實現,數組實現棧更加的常用。因為數組操作的常數時間極短,而且實現起來更加簡單。
 1public class StackImplementByArray<AnyType> {
2    AnyType[] arr;
3    int size;
4    public void stack(int capacity){
5        arr=(AnyType[])new Object[capacity];
6        size=0;
7    }
8    public void push(AnyType a){
9        if(size==arr.length){
10            changeArray(2*size+1);
11        }
12        arr[size]=a;
13        size++;
14    }
15    public AnyType pop(){
16        if(size==0){
17            System.out.println("棧頂為空");
18            System.exit(0);
19        }
20        AnyType a=arr[size-1];
21        arr[size-1]=null;
22        size--;
23        return a;
24    }
25    public boolean isEmpty(){
26        return size==0;
27    }
28    public int size(){
29        return size;
30    }
31
32    //由於數組大小是要先確定的,因此當數組滿了后要擴大數組容量
33    public void changeArray(int newCapacity){
34        AnyType[] newArr=(AnyType[])new Object[newCapacity];
35        for(int i=0;i<arr.length;i++){
36            newArr[i]=arr[i];
37        }
38        arr=newArr;
39    }
40
41}

棧的應用

  • 平衡符號的檢測

編譯器檢查程序符號的語法錯誤,常常就是通過棧來實現的。

在編程時,我們經常會用到“ ( ),[ ],{ }," " ”這些符號,當這些符號不是配對出現的,編譯器就會報錯,編譯就無法通過。

那么,編譯器是怎么知道這些符號有沒有配對出現的呢?它通常是這么處理的。

當遇到左符號,如“( [ { " ”這些,就把它壓入一個准備好的棧;否則就彈出棧頂,檢測當前符號是否與棧頂元素配對。一旦不能配對,直接退出報錯。

  • 算術表達式的求值

棧的應用-逆波蘭式

隊列

隊列模型

wiki: 隊列,又稱為佇列(queue),是先進先出(FIFO, First-In-First-Out)的線性表。在具體應用中通常用鏈表或者數組來實現。隊列只允許在后端(稱為rear)進行插入操作,在前端(稱為front)進行刪除操作。隊列的操作方式和堆棧類似,唯一的區別在於隊列只允許新數據在后端進行添加。

隊列模型就相當於我們日常生活的排隊,在隊伍的后面入隊,在隊伍的前端出隊。

多種隊列

隊列一般分為普通的數組隊列,鏈表隊列和循環隊列。

鏈表隊列:長度一般是無限的,一般不存在溢出的可能性,用完就銷毀,不會浪費內存空間。

普通的數組隊列:長度一般是有限的,即數組長度。由於元素出隊后其位置的內存空間並不會釋放,因此會浪費大量的內存空間。

循環隊列:特殊的數組隊列,由於普通的數組的隊列會浪費大量的內存空間,因此出現了循環隊列。當循環隊列的隊尾指針到達數組末尾后,會重新回到數組起始位置,實現了對內存的重復利用。

隊列的實現

1.鏈表隊列

 1public class QueueImplementByLinkList<AnyType{
2    Node first;//隊首
3    Node last;//隊尾
4    int size;
5    public class Node{
6        AnyType data;
7        Node next;
8        public Node(AnyType data,Node next){
9            this.data=data;
10            this.next=next;
11        }
12    }
13
14    //初始化隊列
15    public void initqueue(){
16        first=new Node(null,null);
17        last=first;
18        size=0;
19    }
20
21    //入隊
22    public void enqueue(AnyType a){
23        if(size==0){
24            last.data=a;
25            size++;
26            return;
27        }
28        Node oldlast=last;
29        last=new Node(a,null);
30        oldlast.next=last;
31        size++;
32    }
33
34    //出隊
35    public AnyType dequeue(){
36        if(size==0){
37            System.out.print("隊列為空");
38            System.exit(0);
39        }
40        AnyType a=first.data;
41        first=first.next;
42        size--;
43        return a;
44    }
45    public boolean isEmpty(){
46        return size==0;
47    }
48    public int size(){
49        return size;
50    }
51}

2.數組隊列

 1public class QueueImplementByArray<AnyType> {
2    AnyType[] arr;
3    int first;
4    int last;
5    int size;
6    //初始化
7    public void ininqueue(int capacity){
8        arr=(AnyType[])new Object[capacity];
9        first=0;
10        last=0;
11        size=0;
12    }
13    public void enqueue(AnyType a){
14        if(size==arr.length){
15            changeArray(2*size+1);
16        }
17        arr[last++]=a;
18        size++;
19    }
20    public AnyType dequeue(){
21        if(size==0){
22            System.out.println("隊列為空");
23            System.exit(0);
24        }
25        AnyType a=arr[first++];
26        arr[first-1]=null;
27        size--;
28        return a;
29    }
30    public void changeArray(int newCapacity){
31        AnyType[] newArr=(AnyType[])new Object[newCapacity];
32        for(int i=0;i<arr.length;i++){
33            newArr[i]=arr[i];
34        }
35        arr=newArr;
36    }
37    public boolean isEmpty(){
38        return size==0;
39    }
40    public int size(){
41        return size;
42    }
43
44}
  1. 循環隊列
 1public class CycleQueue {
2    int[] arr;
3    int start;//隊首
4    int end;//隊尾
5    int size=0;
6    //初始化
7    public void initqueue(int size){
8        arr=new int[size];
9        size=0;
10        start=0;
11        end=0;
12    }
13
14    //入隊
15    public void enqueue(int num){
16        if(size>arr.length){
17            System.out.println("隊列已滿");
18            return;
19        }
20        if(end==arr.length){
21            end=0;
22        }
23        arr[end++]=num;
24        size++;
25    }
26
27    //出隊
28    public int dequeue(){
29        if(size==0){
30            System.out.println("隊列為空");
31            System.exit(0);
32        }
33        if(start==arr.length){
34            start=0;
35        }
36        size--;
37        return arr[start++];
38    }
39
40    public boolean isEmpty(){
41        return size==0;
42    }
43    public int size(){
44        return size;
45    }
46}

一點點總結

棧和隊列是基本的數據結構,是對數組和鏈表的重新封裝和擴展。由於它們的特性和執行速度,棧和隊列被廣泛的使用。

最后,不要為了使用數據結構而使用使用數據結構,要區分各種數據結構的使用場景,靈活地運用數據結構,可以事半功倍。

如果這篇文章對你有幫助的話,左下角給個推薦鴨,這個對我真的很重要?!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM