javascript中的棧結構

ndblog發表於2016-08-23

1.棧的定義

  棧是一種和列表類似的資料結構,可以用它來解決很多的程式設計問題,棧是一種高效的資料結構,因為資料只能在棧的頂端新增或者刪除,所以這樣的操作很快而且容易實現。

  棧是一種特殊的列表,站內的元素只能拖過列表的一端進行訪問,這一端陳偉棧頂。一疊盤子是最常見的棧結構,只能從頂部取盤子,洗好的盤子也只能放在頂端。棧被稱為後入先出的資料結構。

  由於棧具有後入先出的特點,所以任何不在棧頂的元素都無法訪問。為了得到棧底的元素,必須拿掉上面的元素。

  對棧的操作有將一個元素壓入棧和將一個元素彈出棧。把元素壓入棧頂使用push()方法,從棧頂彈出元素使用pop()方法。還有一個方法是預覽棧頂元素,使用pop()方法雖然可以訪問棧頂的元素,但是呼叫該方法後棧頂的元素將被永久的刪除。peek()方法只返回棧頂的元素,而不刪除它。

  為了記錄棧頂元素的位置,同時也為了標記從哪裡可以加入新元素,我們使用變數top,當向棧內壓入元素是該變數增大,從站內彈出元素時,該變數減小。

  pop(),push(),peek()方法是最主要的三個方法,同時定義clear()方法可以清楚棧內所有的元素,length屬性定義棧內元素的個數,同時定義一個empty屬性標識棧內是否還有元素,不過使用length屬性可以達到同樣的目的。

棧結構的程式碼如下:

//使用陣列dataStore儲存站內元素,建構函式將其初始化為一個空陣列。
//變數top定義棧頂的位置,構造時初始化為0,表示棧的起始位置為0
function Stack(){
    this.dataStore = [];
    this.top = 0;
    this.push = push;
    this.pop = pop;
    this.peek = peek;
    this.clear = clear;
    this.length = length;

    //注意++操作符的位置,它放在this.top的後面,這樣新入棧的元素就被放在top的當前位置對應的位置,同時top自加1,指向下一個位置
    function push(element){
        this.dataStore[this.top++] = element;
    }
    //返回棧頂元素,同時top的位置減1
    function pop(){
        return this.dataStore[--this.top];
    }
    //peek()方法返回陣列的第top-1個位置的元素,即棧頂元素
    function peek(){
        return this.dataStore[this.top-1];
    }
    //將top的值設定0,即清空一個棧
    function clear(){
        this.top = 0;
    }
    //返回變數top的值即為棧內元素的個數
    function length(){
        return this.top;
    }
}

使用下面的程式碼來檢驗棧結構

var s = new Stack();
s.push("David");
s.push("Baymond");
s.push("Bryan");
document.writeln("length:" + s.length());
document.writeln(s.peek());
var popped = s.pop();
document.writeln("the popped element is:" + popped);
document.writeln(s.peek());
s.push("Cynthia");
document.writeln(s.peek());
s.clear();
document.writeln("length:" + s.length());
document.writeln(s.peek());
s.push("Clayton");
document.writeln(s.peek());

輸出如下:

length:3 
Bryan 
the popped element is:Bryan 
Baymond 
Cynthia 
length:0 
undefined 
Clayton

 

2.用棧實現進位制轉換

可以使用棧將一個數字從一種數制轉換成另一種數制,假設想將數字n轉換為以b為基數的數字,實現方法如下:

(1)最高位為n%b,將此位壓入棧

(2)使用n/b代替n

(3)重複(1),(2)直到n等於0,且沒有餘數

(4)持續將站內元素彈出,直達棧為空,依次將這些元素排列,就得到轉換後的數字的字串形式

來看下面的程式碼,如何將數字轉換為2進位制和8進位制

function mulBase(num,base){
    var s = new Stack();
    do{
        s.push(num % base);
        num = Math.floor( num /= base );
    }while(num>0);
    var converted = "";
    while (s.length()>0){
        converted += s.pop();
    }
    
    return converted;
}

var num = 32;
var base = 2;
var newNum = mulBase(num, base);
document.writeln(num + " converted to base " + base + " is " + newNum);
num = 125;
base = 8;
newNum = mulBase(num, base);
document.writeln(num + " converted to base " + base + " is " + newNum);

最後輸出的結果如下:

32 converted to base 2 is 100000 125 converted to base 8 is 175

 

3.用棧判斷迴文

  迴文是這樣一種現象:一個單詞,短語或者數字,從前往後和從後往前寫都是一樣的。比如單詞“dad”,“racecar”就是迴文;如果忽略空格和標點符號,下面這個句子也是迴文,“A man, a plan, a canal: Panama”,數字1001也是迴文。

  使用棧可以輕鬆的判斷一個字元是否是迴文。我們將拿到的字串的每個字元按照從左至右的順序入棧,當所有字元都入棧之後站內就儲存了一個反轉後的字串,最後的字元在棧頂,第一個在棧尾。字串完全壓入站內後,通過持續彈出棧中的每個字母就可以的大一個新的字串,該字串剛好與原來的字串順序相反。我們只要比較這兩個字串即可,如果他們相等就說明這個是一個迴文。程式碼如下:

function isPalindrome(word){
    var s = new Stack();
    for (var i=0; i<word.length; ++i) {
        s.push(word[i]);
    }
    var reword = "";
    while(s.length()>0){
        reword += s.pop();
    }
    if(word == reword){
        return true;
    }else{
        return false;
    }    
}

var word = "hello";
if(isPalindrome(word)){
    document.writeln(word + " is a palindrome.");
}else{
    document.writeln(word + " is not a palindrome");
}
word = "racecar";
if(isPalindrome(word)){
    document.writeln(word + " is a palindrome.");
}else{
    document.writeln(word + " is not a palindrome");
}

輸出結果如下:

hello is not a palindrome
racecar is a palindrome. 

 

4.用棧實現遞迴

遞迴是一種很常見的演算法,使用棧來實現遞迴是一件很輕鬆的事情,例如計算階乘可以使用遞迴演算法,如下:

function factorial(n) {
    if (n === 0) {
        return 1;
    }
    else {
        return n * factorial(n-1);
    }
}

使用棧來模擬階乘過程,例如:首先將5到1壓入棧內,然後使用給一個迴圈,將數字一次彈出連乘就得到正確的答案,程式碼如下:

function fact(n){
    var s = new Stack();
    while (n>1){
        s.push(n--);
    }
    var product = 1;
    while (s.length()>0){
        product *= s.pop();
    }
    return product;
}
document.writeln(fact(5));

結果如下:

120

 5.使用棧判斷表示式中的括號是否完整

表示式中的{和},(和),[和]必須是匹配的,不然的話表示式就會出現語法錯誤,使用棧可以判斷表示式中的括號是否左右匹配。思路是遇到左括號就入棧,遇到右括號就和當前棧頂元素匹配,如果匹配成功就將棧頂元素出棧,最後判斷棧中元素個數,如果是0就代表是完整的,否則就是不完整的。程式碼如下:

function isMatch(str){
    var left = "({[";
    var right = ")}]";
    var s = new Stack();
    var i = 0;
    while (str[i]){
        //左符號入棧
        if(left.indexOf(str[i])>-1){
            s.push(str[i])
        }
        //遇到右括號
        else if( right.indexOf(str[i])>-1 && right.indexOf( str[i] ) == left.indexOf( s.peek()) ){
            s.pop();
        }
        i++
    }
    
//    document.writeln( s.peek() );
    if(s.length() == 0){
        document.writeln(str + " is match success");
    }else{
        document.writeln(str + " is not match");
    }
}

isMatch("2.3 + {23 / 12 + (3.14159×0.24)");

 

作者:Tyler Ning

出處:http://www.cnblogs.com/tylerdonet/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,如有問題,可以通過以下郵箱地址williamningdong@gmail.com
 聯絡我,非常感謝。


相關文章