棧是一種聽從後進先出(LIFO)原則的有序集合。新添加或待刪除的元素都保存在棧的同一端,稱做棧頂,另外一端就叫棧底。在棧裏,新元素都靠近棧頂,舊元素都靠近棧底。git
現實生活中典型的棧的例子就是一摞書或者餐廳裏疊放的盤子。算法
建立一個類來表示棧。數組
class Stack {
constructor() {
this.items = [];
}
}
複製代碼
實現方法push,添加一個(或幾個)新元素到棧頂。bash
push(element) {
this.items.push(element);
}
複製代碼
實現方法pop,移除棧頂的元素,同時返回被移除的元素。數據結構
pop() {
return this.items.pop();
}
複製代碼
實現方法peek,返回棧頂的元素,不對棧作任何修改。學習
peek() {
return this.items[this.items.length -1];
}
複製代碼
實現方法isEmpty,若是棧裏沒有任何元素就返回true,不然返回false。ui
isEmpty() {
return this.items.length === 0;
}
複製代碼
實現方法clear,移除棧裏的全部元素。this
clear() {
this.items = [];
}
複製代碼
實現方法size,返回棧裏的元素個數。該方法和數組的length屬性很相似。spa
size() {
return this.items.length;
}
複製代碼
class Stack {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
return this.items.pop();
}
peek() {
return this.items[this.items.length -1];
}
isEmpty() {
return this.items.length === 0;
}
clear() {
this.items = [];
}
size() {
return this.items.length;
}
}
複製代碼
首先初始化Stack類,而後驗證一下棧是否爲空。code
const stack = new Stack();
console.log(stack.isEmpty()); // 輸出爲true
複製代碼
往棧裏添加元素5,8
stack.push(5);
stack.push(8);
複製代碼
調用peek方法
console.log(stack.peek()); // 8
複製代碼
再添加一個元素
stack.push(11);
console.log(stack.size()); // 3
console.log(stack.isEmpty()); // false
複製代碼
最後,再添加一個元素
stack.push(15);
console.log(stack.size()); // 4
複製代碼
而後,調用兩次pop方法從棧裏移除兩個元素。
stack.pop();
stack.pop();
console.log(stack.size()); // 2
複製代碼
建立一個Stack類最簡單的方式是使用一個數組來存儲其元素。在處理大量數據的時候,咱們須要評估如何操做數據最高效。在使用數組時,大部分方法的時間複雜度是O(n),另外,數組是元素的一個有序集合,爲了保證元素排列有序,它會佔用更多的內存空間。
爲了解決上述問題,咱們能夠使用一個JavaScript對象來存儲全部的棧元素,保證它們的順序而且遵循LIFO原則。
首先聲明一個Stack類。
class Stack {
constructor() {
this.count = 0;
this.items = {};
}
}
複製代碼
push(element) {
this.items[this.count] = element;
this.count++;
}
複製代碼
size() {
return this.count
}
isEmpty() {
return this.count === 0;
}
複製代碼
pop() {
if(this.isEmpty()) {
return undefined;
}
this.count--;
const result = this.items[this.count];
delete this.items[this.count];
return result;
}
複製代碼
peek() {
if(this.isEmpty()) {
return undefined;
}
return this.items[this.count -1]
}
clear() {
this.items = {};
this.count = 0;
}
複製代碼
toString() {
if(this.isEmpty()) {
return ''
}
let objString = `${this.items[0]}`;
for(let i = 1; i < this.count; i++) {
objString = `${objString},${this.items[i]}`
}
return objString;
}
複製代碼
十進制轉化成二進制,能夠將十進制數除以2(二進制是滿二進一)並對商取整,直到結果是0爲止。
function decimalToBinary(decNumber) {
const remStack = new Stack();
let number = decNumber;
let rem;
let binaryString = '';
while(number > 0) {
rem = Math.floor(number % 2);
remStack.push(rem);
number = Math.floor(number / 2);
}
while(!remStack.isEmpty()) {
binaryString += remStack.pop().toString();
}
return binaryString;
}
console.log(decimalToBinary(233));
console.log(decimalToBinary(10));
console.log(decimalToBinary(1000));
複製代碼
咱們能夠修改上述算法,使之能把十進制轉換成基數爲2~36的任意進制。
function baseConverter(decNumber, base) {
const remStack = new Stack();
const digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
let number = decNumber;
let rem;
let baseString = '';
if(!(base >=2 && base <= 36)) {
return '';
}
while(number > 0) {
rem = Math.floor(number % base);
remStack.push(rem);
number = Math.floor(number / base);
}
while(!remStack.isEmpty()) {
baseString += digits[remStack.pop()];
}
return baseString;
}
console.log(baseConverter(100345,2));
console.log(baseConverter(100345,8));
console.log(baseConverter(100345,16));
console.log(baseConverter(100345,35));
複製代碼
本節學習了棧這一數據結構的相關知識。使用數組和JavaScript對象實現了棧,還涉及瞭如何用push和pop往棧裏添加和移除元素。
給定一個只包括 '(',')','{','}','[',']'的字符串,判斷字符串是否有效。 有效字符串需知足: 左括號必須用相同類型的右括號閉合。 左括號必須以正確的順序閉合。 注意空字符串可被認爲是有效字符串。
思路:當遇到右邊的括號時,入棧,當遇到左邊的括號時,判斷棧頂是否與左邊的括號匹配,若是不是的話,直接返回false,若是是進行下一次判斷,循環結束,若是棧爲空,則返回true,若是不爲空,則返回false。
function(s) {
const item = [];
const opens = '([{';
const closers = ')]}';
let index = 0;
let symbol;
let top;
while (index < s.length) {
symbol = s[index];
if (opens.indexOf(symbol) >= 0) {
item.push(symbol);
} else {
top = item.pop();
if (!(opens.indexOf(top) === closers.indexOf(symbol))) {
return false;
}
}
index++;
}
return item.length === 0;
};
複製代碼