1. 程式人生 > >棧和佇列的基本應用

棧和佇列的基本應用

棧的使用

給定一個字串,只包含{,[, (,),],},判斷字串的括號匹配是否合法。如(),()[]{}是合法的,而(]是不合法的
假設一個字串’{[()]}’,當我們遍歷時遇到左操作符的時候,就將它壓入棧中,當遇到右操作符的時候,就與棧頂的元素匹配,如果match就將棧頂的左操作符彈出,繼續遍歷。如果沒有match的話就返回false。如果遍歷結束的時候棧也為空,這個字元就是合法的。

   function isValid(str){
      for(var i = 0, len = str.length; i < len; i++){
         if(str[i] == '('
|| str[i] == '{' str[i] == '[' ){ stack.push(str[i]) } else { if(stack.size == 0) return false; var c = stack.pop(); //省略match定義 if(!str[i].match(c)){ return false; } } } if(stack.size == 0
) { return true; } else { return false; } }

棧頂元素反映了在巢狀的層次關係中,最近的需要匹配的元素

棧和遞迴的緊密關係

我們先看一下二叉樹的先序遍歷

   function preorder(node){
      if(node){
         console.log(node.value);
         preorder(node.left);
         preorder(node.right);
      }
   }

我們來看一下具體的遍歷,假設我們只有三個節點,父節點是1,左節點是2,右節點是3。我們首先使用根節點呼叫函式preorder,然後使用節點2呼叫了函式preorder,再使用節點3呼叫了函式preorder。這三次preorder的傳入引數是不同的,那麼這三個函式的呼叫順序是怎麼樣的?我們可以抽象為根節點呼叫時,執行到節點2呼叫的時候停住了,接著執行一個子函式也就是節點2的呼叫,直到節點2呼叫結束之後,再進行節點3子函式的呼叫。那麼作業系統就是通過棧來實現這樣一個操作。根節點呼叫的函式先被壓入棧中開始執行,這時遇到了函式棧節點2。在節點2的函式被壓入棧之後立即執行,等到執行完之後返回值(或不返回),然後節點2的函式被彈出。節點2的函式被彈出之後,節點1的函式繼續執行,節點3的函式被壓入並立即執行。

佇列的基本應用

佇列比較常用的是廣度優先遍歷,在樹中是層序遍歷,在圖中是無權圖的最短路徑
我們來看一下二叉樹的層序遍歷

    var node;
    levelOrder(root){
       var result = [];
       if(root == null) return result;
       queue.push(root);
       while(!queue.empty()){
           var node = queue.front();
           if(node.left) queue.push(node.left);
           if(node.right) queue.push(node.right);
       result.push(node.value);
       }
    }