javascript中的栈结构

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)");
原文地址:https://www.cnblogs.com/tylerdonet/p/5801248.html