栈是一种遵循后进先出(LIFO)原则的有序集合。新添加的或待删除的元素都保存在栈的末尾,称作栈顶,另一端就叫栈底。在栈里,新元素都靠近栈顶,旧元素都接近栈底。
现实生活中有很多栈的例子,如一摞书或者餐厅里堆放的盘子。
接下来将创建一个类来表示栈,先声明类:
function Stack() {
/*
* 我们可以使用数组来保存栈里的元素,然后声明一些操作栈的方法:
* push(element):添加一个(或几个)新元素到栈顶。
* pop():移除栈顶的元素,同时返回被移除的元素。
* peek():返回栈顶的元素,不对栈做任何修改(这个方法不会移除栈顶的元素,仅仅返回它)。
* isEmpty():如果栈里没有任何元素就返回true,否则返回false。
* clear():移除栈里的所有元素。
* size():返回栈里的元素个数,这个方法和数组的length属性很类似。
* print():以字符串形式打印当前的数组。
*/
const items = [];
this.push = function (element) {
items.push(element);
};
this.pop = function () {
return items.pop();
};
this.peek = function () {
return items[items.length - 1];
};
this.isEmpty = function () {
return items.length === 0;
};
this.clear = function () {
items= [];
};
this.size = function () {
return items.length;
};
this.print = function () {
consle.log(items.toString());
};
}
使用栈的方法前,先实例化栈:const stack = new Stack();
使用栈的push方法向栈中添加数据,形式如下图,最先添加的元素总是位于栈底,最后添加的元素总是位于栈顶。
1、stack.push(5,8);
2、stack.push(11);
3、stack.push(15);
使用栈的pop方法从栈中移除数据,形式如下图,最先移除的元素总是位于栈顶,最后移除的元素总是位于栈底。
1、stack.pop();
2、stack.pop();
实战:使用栈的方式进行十进制转换
一、从十进制到二进制
要把十进制转化成二进制,我们可以将该十进制数字和2整除(二进制是满二进一),直到结果是0为止。举个例子,把十进制的数字10转化成二进制的数字,过程大概是这样:
1、将余数放入栈中;
2、输出=将余数移除;
3、十进制10=>二进制1010。
十进制转换成二进制的算法描述如下:
/*
* decNumber:需要转换的进制数值。
* remStack :栈的实例化。
* rem:每次整除的余数。
* binaryString:转化后的二进制数值。
*/
function divideBy2(decNumber) {
const remStack = new Stack(),
let rem,
let binaryString = '';
while (decNumber > 0) {
rem = Math.floor(decNumber % 2);
remStack.push(rem);
decNumber = Math.floor(decNumber / 2);
}
while (!remStack.isEmpty()) {
binaryString += remStack.pop().toString();
}
return binaryString;
}
console.log(divideBy2(10)); //1010
在上面这段代码里,当结果满足和2做整除的条件时,我们会获得当前结果和2的余数,放到栈里。然后让结果和2做整除。另外请注意:JavaScript有数字类型,但是它不会区分究竟是整数还是浮点数。因此,要使用Math.floor函数让除法的操作仅返回整数部分。最后,用pop方法把栈中的元素都移除,把出栈的元素连接成字符串。
我们很容易修改上面的算法,使之能把十进制转换成任何进制。除了让十进制数字和2整除转成二进制数,还可以传入其他任意进制的基数为参数,就像下面算法这样:
/*
* decNumber:需要转换的进制数值。
* base:目标进制基数。
* remStack:栈的实例化。
* rem:每次整除的余数。
* digits:显示位数(需转化内容)。
* baseString:转化后的进制数值。
*/
function baseConverter(decNumber, base) {
const remStack = new Stack(),
let rem,
let baseString = '',
let digits = '0123456789ABCDEF';
while (decNumber > 0) {
rem = Math.floor(decNumber % base);
remStack.push(rem);
decNumber = Math.floor(decNumber / base);
}
while (!remStack.isEmpty()) {
baseString += digits[remStack.pop()];
}
return baseString;
}
console.log('二进制', baseConverter(100345, 2)); //二进制 11000011111111001
console.log('八进制', baseConverter(100345, 8)); //八进制 303771
console.log('十六进制', baseConverter(100345, 16)); //十六进制 187F9
在将十进制转成二进制时,余数是0或1;在将十进制转成八进制时,余数是0到7之间的数;但是将十进制转成16进制时,余数是0到9之间的数字加上A、B、C、D、E和F(对应10、11、12、13、14和15)。因此,我们需要对栈中的数字做个转化才可以。