棧是一種遵循後進先出(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)。因此,我們需要對棧中的數字做個轉化纔可以。