<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          棧棧棧棧棧棧棧棧棧棧棧棧棧棧棧棧棧棧

          共 4262字,需瀏覽 9分鐘

           ·

          2021-03-01 18:09

          大家好,我是沉默王二。

          今天周一,又是 3 月份的第一天,所以今天必須來點(diǎn)硬核的內(nèi)容。

          上次給大家圖解了霍夫曼編碼,有同學(xué)說每天早上都會(huì)看一篇二哥的文章,但因?yàn)檫@一篇星標(biāo)了;還有做律師的同學(xué)亂入,表示雖然看不懂,但感覺很厲害;當(dāng)然了,更多的同學(xué)對(duì)文中提到的知識(shí)點(diǎn)進(jìn)行了思考,有些得出了自己的結(jié)論,有些沒有,但不管有沒有結(jié)論,重要的是主動(dòng)去思考,也只有這樣,才能收獲更多!

          還有很多同學(xué)直呼內(nèi)行,強(qiáng)烈要求我多更一些這方面的文章,于是就有了今天這篇——棧(stack)。有些地方喜歡稱呼它為堆棧,我就很不喜歡,很容易和 heap(堆)搞混,尤其是對(duì)于新手來說,簡直就是虐心。

          棧是一種非常有用的數(shù)據(jù)結(jié)構(gòu),它就像一摞盤子,第一個(gè)放在最下面,第二個(gè)放在第一個(gè)上面,第三個(gè)放在第二個(gè)上面,最后一個(gè)放在最上面。

          對(duì)于這一摞盤子,我們可以做兩件事情:

          • 在最上面放一個(gè)新盤子
          • 把頂部的盤子拿走

          這兩件事情做起來很容易,但如果從中間或者底部抽出來一個(gè)盤子,就很難辦到。如果我們想要拿到最下面的盤子,就必須把它上面的所有盤子都拿走,像這樣的一個(gè)操作,我們稱之為后進(jìn)先出,也就是“Last In First Out”(簡稱LIFO)——最后的一個(gè)進(jìn)的,最先出去。

          對(duì)于棧這樣一個(gè)數(shù)據(jù)結(jié)構(gòu)來說,它有兩個(gè)常見的動(dòng)作:

          • push,中文釋義有很多種,我個(gè)人更喜歡叫它“壓入”,非常形象。當(dāng)我們要把一個(gè)元素放入棧的頂部,這個(gè)動(dòng)作就叫做 push

          • pop,同樣的,我個(gè)人更喜歡叫它“彈出”,帶有很強(qiáng)烈的動(dòng)畫效果,有沒有?當(dāng)我們要從棧中移除一個(gè)元素時(shí),這個(gè)動(dòng)作就叫做 pop

          對(duì)于上面這幅圖來說,3 這個(gè)元素最先放進(jìn)去,卻是最先被移除的——遵循 LIFO 的原則。

          明白了棧的基本操作后,我們需要去深入地思考一下,棧是如何工作的。換句話說,為了使棧這個(gè)數(shù)據(jù)結(jié)構(gòu)按照棧的方式去工作,它需要什么?

          1)棧需要有一個(gè)指針,我們稱之為 TOP,用它來指向棧中最頂部的那個(gè)元素。

          2)當(dāng)我們初始化一個(gè)棧的時(shí)候,我們把 TOP 的值設(shè)置為 -1,這樣我們就可以通過 TOP == -1 來判斷棧是否為空。

          3)當(dāng)我們要在棧中壓入一個(gè)元素的時(shí)候,我們把 TOP 的值加 1,然后把新壓入的元素指向 TOP。

          4)當(dāng)我們要從棧中彈出一個(gè)元素的時(shí)候,我們把 TOP 的值減 1,然后把保持在最頂部的那個(gè)元素指向 TOP。

          5)當(dāng)我們壓入一個(gè)元素的時(shí)候,需要檢查棧是否已經(jīng)滿了。也就是說,需要有一個(gè) isFull() 的方法來判斷。

          6)當(dāng)我們要彈出一個(gè)元素的時(shí)候,需要檢查棧是否已經(jīng)空了。也就是說,需要有一個(gè) isEmpty() 的方法來判斷。

          空棧的時(shí)候,TOP 等于 -1;把元素 1 壓入棧中的時(shí)候,stack[0] 為 1,TOP 加 1 變?yōu)?0;把元素 2 壓入棧中的時(shí)候,stack[1] 為 2,TOP 加 1 變?yōu)?1;把元素 3 壓入棧中的時(shí)候,stack[2] 為 3,TOP 加 1 變?yōu)?2;把元素 3 從棧中彈出后,返回元素 stack[2],TOP 減 1 變?yōu)?1。

          假設(shè)棧中的元素是 int 類型,我們可以用 Java 語言來自定義一個(gè)最簡單的棧。它需要 3 個(gè)字段:

          • int arr[],一個(gè) int 類型的數(shù)組,來存放數(shù)據(jù)
          • int top,一個(gè) int 類型的標(biāo)記
          • int capacity,一個(gè) int 類型的容量
          class Stack {
              private int arr[];
              private int top;
              private int capacity;
          }

          初始化棧:

          Stack(int size) {
              arr = new int[size];
              capacity = size;
              top = -1;
          }

          往棧中壓入元素:

          public void push(int x) {
              if (isFull()) {
                  System.out.println("溢出\n程序終止\n");
                  System.exit(1);
              }

              System.out.println("壓入 " + x);
              arr[++top] = x;
          }

          從棧中彈出元素:

          public int pop() {
              if (isEmpty()) {
                  System.out.println("棧是空的");
                  System.exit(1);
              }
              return arr[top--];
          }

          返回棧的大小:

          public int size() {
              return top + 1;
          }

          檢查棧是否為空:

          public Boolean isEmpty() {
              return top == -1;
          }

          檢查棧是否已經(jīng)滿了:

          public Boolean isFull() {
              return top == capacity - 1;
          }

          來個(gè) main() 方法直接測試下:

          public void printStack() {
              for (int i = 0; i <= top; i++) {
                  System.out.println(arr[i]);
              }
          }

          public static void main(String[] args) {
              Stack stack = new Stack(5);

              stack.push(1);
              stack.push(2);
              stack.push(3);
              stack.push(4);

              stack.pop();
              System.out.println("\n彈出元素后");

              stack.printStack();
          }

          打印結(jié)果如下所示:

          壓入 1
          壓入 2
          壓入 3
          壓入 4

          彈出元素后
          1
          2
          3

          由于我們是通過數(shù)組來實(shí)現(xiàn)的棧,所以 pushpop 的時(shí)間復(fù)雜度就是 O(1)

          盡管棧是一種非常簡單的數(shù)據(jù)結(jié)構(gòu),通過上面的代碼大家應(yīng)該也能感受得出來,輕而易舉地就實(shí)現(xiàn)了,但是棧卻是一種非常強(qiáng)有力的數(shù)據(jù)結(jié)構(gòu),可以在很多場景中使用,比如說:

          1)反轉(zhuǎn)一串字符:由于棧是 LIFO 的,所以反轉(zhuǎn)一串字符很容易,按照正常的順序把字符壓入棧中,然后再彈出來就行了。

          2)用于計(jì)算器:記得我實(shí)習(xí)的時(shí)候,公司就給我們新人安排了我們一個(gè)小項(xiàng)目——模仿一個(gè) Win 7 的計(jì)算機(jī),用來考察我們是不是真材實(shí)料,要想計(jì)算一個(gè)復(fù)雜的表達(dá)式,比如說 2 + 5 / 3 * (6 - 2),就需要一個(gè)棧來容納這些數(shù)字和運(yùn)算符,然后按照優(yōu)先級(jí)彈出后進(jìn)行計(jì)算。

          嗯,這個(gè)計(jì)算要比想象中復(fù)雜一些,新手同學(xué)可以私底下實(shí)現(xiàn)一下,不僅能夠提高對(duì)棧這種數(shù)據(jù)結(jié)構(gòu)的理解,還能對(duì)運(yùn)算符的一個(gè)優(yōu)先級(jí)進(jìn)行思考。

          很顯然,棧,給我贏得了一次實(shí)習(xí)的機(jī)會(huì),避免了被刷下去的危機(jī)。

          3)用于瀏覽器:瀏覽器的后退按鈕會(huì)把我們?cè)L問的 URL 壓入一個(gè)棧中,每次我們?cè)L問一個(gè)新的頁面,新的 URL 就壓入了棧的頂部,當(dāng)我們點(diǎn)了后退按鈕,最新的那個(gè) URL 就從棧中移除,之前的那個(gè) URL 就被訪問到了。

          好了,下課,今天的棧就到此為止吧。

          多 BB 一句。上次,很多好心的同學(xué)為了使我吃上香噴噴的辣條,硬是不想學(xué)會(huì)霍夫曼編碼,結(jié)果我真吃了——結(jié)果的結(jié)果——臉上長痘痘了,我想說的是,同學(xué),能不能不要這么貼心,這次學(xué)會(huì)學(xué)不會(huì)我都不吃了,哼。

          瀏覽 45
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日日操视频| 大鸡巴在线视频 | 国产绿奴09-01 | 日韩无码AV片 | 91射射射... |