JavaScript栈数据结构实现与经典应用详解

作者:拾光时间:2026-10-23 10:19:45浏览:80

本文详细解析JavaScript中栈(Stack)数据结构的实现原理,涵盖push、pop、peek等核心方法。通过完整代码示例,演示如何利用栈特性解决数制转换与回文字符串判断两个经典算法问题,帮助开发者深入理解LIFO机制及其在编程中的实际应用。

本文通过具体实例解析JavaScript中算法与数据结构的核心概念——栈(Stack)。内容旨在提供清晰的实现思路与代码参考,供读者学习与应用。

栈(Stack)概述

栈(Stack)

在上一篇关于列表的讨论中,我们了解到列表是一种直观的数据组织方式,适用于对存储顺序要求不高的场景。然而,对于某些特定计算需求(如后缀表达式求值),列表的局限性便显现出来。因此,我们需要一种功能与列表相似但结构更紧凑的数据结构——栈。栈,亦称堆栈,是一种高效的线性数据结构。其核心特征在于元素仅能通过一端(栈顶)进行访问,所有数据的插入(入栈)与删除(出栈)操作均严格遵循“先入后出”(LIFO, Last-In-First-Out)原则。这一特性使其在计算机底层机制及各类算法中有着广泛的应用。栈的基本操作主要包括压入元素(push)和弹出栈顶元素(pop)。此外,栈还具备其他常用属性与方法:通过peek方法可查看当前栈顶元素的值而不将其移除;clear方法用于清空栈内所有数据;top属性用于记录当前栈顶在底层数组中的索引位置;length方法则返回栈中元素的总数量。下文将定义栈的数据类型,并基于JavaScript数组实现其具体功能。

栈(Stack)概述 栈数据类型定义

栈的JavaScript实现

栈的实现


//定义栈

function Stack () {
  this.dataStore = [];  //初始化为空
  this.top = 0;      //记录栈顶位置
  this.pop = pop;     //出栈
  this.push = push;    //入栈
  this.peek = peek;    //查看栈顶元素
  this.length = length;  //查看栈内元素总数
  this.clear = clear;   //清空栈
}

在实现栈时,我们使用dataStore数组来存储栈内元素,初始状态为空数组。同时,引入top属性来记录当前栈顶的位置,初始化值为0。

该top值表示栈顶对应数组的起始索引为0。每当有元素入栈时,top值会随之更新,以指向新的栈顶位置。

首先,我们来实现第一个核心功能:入栈方法。

push:向栈内压入一个新的元素


//该方法将一个新元素入栈,放到数组中 top 所对应的位置上,并将 top 的值加 1,让其指向数组的下一个空位置

function push( element ){
  this.dataStore[this.top++] = element;
}

既然支持入栈,必然需要对应的出栈机制。接下来我们分析出栈方法的实现逻辑:

pop:取出栈顶元素


//该方法与入栈相反,返回栈顶元素,并将 top 的值减 1

function pop(){
  return this.dataStore[--this.top];
}

若需查看栈顶元素而不改变栈状态,可使用peek方法:

peek:查看栈顶元素


//该方法返回的是栈顶元素,即 top - 1 个位置元素

function peek(){
  if( this.top > 0 ) return this.dataStore[this.top-1];
  else return 'Empty';
}

在实现中增加了边界判断:若对空栈调用peek方法,由于栈内无元素,将返回字符串'Empty'。目前,我们已经完成了入栈、出栈及查看栈顶元素这三个基础方法的构建,下面进行实际测试。


//初始化一个栈
var stack = new Stack();
console.log( stack.peek() );  // Empty

//入栈
stack.push('Apple');
stack.push('Banana');
stack.push('Pear');

//查看当前栈顶元素
console.log( stack.peek() );  // Pear
console.log( stack.pop() );   // Pear  

假设我们向栈中压入了一些水果元素,执行一次出栈操作后,如何快速获取剩余元素的数量?此时length方法即可发挥作用。

length:返回栈内元素总数


//该方法通过返回 top 属性的值来返回栈内总的元素个数

function length(){
  return this.top;
}

将代码状态回退至出栈前,即栈内已包含三个水果元素的状态,接着我们验证长度计算:


console.log( stack.length() );   // 3

//出栈
stack.pop();

console.log( stack.length() );   // 2

最后,我们实现最后一个方法clear,用于清空栈。

clear:清空栈


//该方法实现很简单,我们将 top 值置为 0 , dataStore 数值清空即可

function clear(){
  delete this.dataStore;
  this.dataStore = [];
  this.top = 0;
}

通过调用clear方法,我们可以将上述栈实例彻底清空。


stack.clear();

console.log( stack.length() );   // 0
console.log( stack.peek() );    // Empty

至此,我们已利用JavaScript成功实现了一个完整的栈结构。但许多开发者可能仍不清楚如何在实际场景中正确使用栈。接下来,我们将通过两个经典案例,展示栈的具体应用方式。

栈的经典应用场景

案例1:实现数制间的相互转换

利用栈的特性,我们可以轻松实现数字在不同进制间的转换。例如,将十进制数n转换为以b为基数的数,可采用以下算法(该算法适用于基数2至9的情况):

计算最高位:n % b,将结果直接压入栈中; 更新被除数:使用 n / b 的结果替代当前的 n; 重复上述步骤,直到 n 为 0 且无余数; 依次将栈内元素弹出,直到栈为空,并将弹出的元素按顺序排列,即可得到转换后的结果。

具体代码实现如下:


//进制转换(2-9)

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;
}

console.log( mulBase( 125 , 2 ) );   // 1111101
console.log( mulBase( 125 , 8 ) );   // 175

案列2:判断一个字符串是不是回文

回文是指正读和反读结果一致的字符串,例如单词'level'、'racecar',以及数字1001。利用栈的特性,我们可以非常简便地判断字符串是否为回文。算法思路如下:将字符串从左至右依次压入栈中,此时栈内保存了该字符串反转后的字符序列。接着依次弹出栈顶元素,重新拼接成字符串,并与原字符串进行比较。若两者相等,则该字符串为回文。具体代码实现如下:


//回文判断

function isPalindrome ( word ) {
  var s = new Stack();
  for( var i = 0 ; i < word.length ; i ++ ){
    s.push( word[i] );
  }
  var rword = '';
  while( s.length() > 0 ){
    rword += s.pop();
  }

  if( word == rword ){
    return true;
  }else{
    return false;
  }
}

console.log( isPalindrome('level') )  // true
console.log( isPalindrome('1001') )   // true
console.log( isPalindrome('word') )   // false

本文重点在于展示栈的应用,因此采用了上述基于栈的回文判断方式。实际上,若仅需判断回文,使用JavaScript内置方法更为便捷:


function isPalindrome ( word ){
  return String(word).split('').reverse().join('') == word ? true : false;
}

至此,关于栈的核心内容已基本介绍完毕。希望本文能为您带来启发,共同进步。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript数学运算用法总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript数组操作技巧总结》、《JavaScript排序算法总结》、《JavaScript遍历算法与技巧总结》、《JavaScript查找算法技巧总结》及《JavaScript错误与调试技巧总结》

希望本文所述对大家JavaScript程序设计有所帮助。

作者最新文章