首页 » 学习JavaScript数据结构与算法(第2版) » 学习JavaScript数据结构与算法(第2版)全文在线阅读

《学习JavaScript数据结构与算法(第2版)》3.3 用栈解决问题

关灯直达底部

栈的实际应用非常广泛。在回溯问题中,它可以存储访问过的任务或路径、撤销的操作(后面的章节讨论图和回溯问题时,我们会学习如何应用这个例子)。Java和C#用栈来存储变量和方法调用,特别是处理递归算法时,有可能抛出一个栈溢出异常(后面的章节也会介绍)。

既然我们已经了解了Stack类的用法,不妨用它来解决一些计算机科学问题。本节,我们将学习使用栈的三个最著名的算法示例。首先是十进制转二进制问题,以及任意进制转换的算法;然后是平衡圆括号问题;最后,我们会学习如何用栈解决汉诺塔问题。

从十进制到二进制

现实生活中,我们主要使用十进制。但在计算科学中,二进制非常重要,因为计算机里的所有内容都是用二进制数字表示的(0和1)。没有十进制和二进制相互转化的能力,与计算机交流就很困难。

要把十进制转化成二进制,我们可以将该十进制数字和2整除(二进制是满二进一),直到结果是0为止。举个例子,把十进制的数字10转化成二进制的数字,过程大概是这样:

大学的计算机课一般都会先教这个进制转换。下面是对应的算法描述:

function pideBy2(decNumber){  var remStack = new Stack,    rem,    binaryString = '';  while (decNumber > 0){ //{1}    rem = Math.floor(decNumber % 2); //{2}    remStack.push(rem); //{3}    decNumber = Math.floor(decNumber / 2); //{4}  }  while (!remStack.isEmpty){ //{5}    binaryString += remStack.pop.toString;  }  return binaryString;}  

在这段代码里,当结果满足和2做整除的条件时(行{1}),我们会获得当前结果和2的余数,放到栈里(行{2}{3})。然后让结果和2做整除(行{4})。另外请注意:JavaScript有数字类型,但是它不会区分究竟是整数还是浮点数。因此,要使用Math.floor函数让除法的操作仅返回整数部分。最后,用pop方法把栈中的元素都移除,把出栈的元素变成连接成字符串(行{5})。

用刚才写的算法做一些测试,使用以下代码把结果输出到控制台里:

console.log(pideBy2(233));console.log(pideBy2(10));console.log(pideBy2(1000));  

进制转换算法

我们很容易修改之前的算法,使之能把十进制转换成任何进制。除了让十进制数字和2整除转成二进制数,还可以传入其他任意进制的基数为参数,就像下面算法这样:

function baseConverter(decNumber, base){  var remStack = new Stack,    rem,    baseString = '',    digits = '0123456789ABCDEF'; //{6}  while (decNumber > 0){    rem = Math.floor(decNumber % base);    remStack.push(rem);    decNumber = Math.floor(decNumber / base);  }  while (!remStack.isEmpty){    baseString += digits[remStack.pop]; //{7}  }  return baseString;}  

我们只需要改变一个地方。在将十进制转成二进制时,余数是0或1;在将十进制转成八进制时,余数是0到7之间的数;但是将十进制转成16进制时,余数是0到9之间的数字加上A、B、C、D、E和F(对应10、11、12、13、14和15)。因此,我们需要对栈中的数字做个转化才可以(行{6}和行{7})。

可以使用之前的算法,输出结果如下:

console.log(baseConverter(100345, 2));console.log(baseConverter(100345, 8));console.log(baseConverter(100345, 16));  

 请在网上下载本书的代码,里面还有一些栈的应用实例,如平衡圆括号和汉诺塔。