javascript資料結構與演算法筆記(一):棧
阿新 • • 發佈:2018-12-12
javascript資料結構與演算法筆記(一):棧
一:簡介
棧是一種遵從後進先出( LIFO)原則的有序集合。新新增的或待刪除的元素都儲存在棧的
同一端,稱作棧頂,另一端就叫棧底。在棧裡,新元素都靠近棧頂,舊元素都接近棧底。
二:ES6版Stack類(陣列)
1.宣告Stack類
class Stack{
constructor(){
this.items=[];
}
}
2.向棧新增元素
只需與構建函式constructor()同級命名建立即可,下同。
push(element){
items.push(element);
}
3.從棧移除元素
pop方法會刪除原棧中的元素
pop(){
return items.pop();
}
4.檢視棧頂元素
peek(){
return items[items.length-1];
}
5.檢查棧是否為空
isEmpty,如果棧為空的話將返回true,否則就返回false:
isEmpty(){
return items.length==0;
}
size(){
return items.length;
}
6.清空棧
isEmpty(){
return items=[];
}
7.列印棧元素
print(){
console.log(items.toString());
//或者
console.log(items.join(","));
}
8.使用棧
let stack=new Stack();
console.log(stack.isEmpty());
stack.push(1);
stack.push(2);
console. log(stack.size());
console.log(stack.peek());
console.log(stack.size());
console.log(stack.pop());
stack.print();
注:使用es6的class封裝的Stack,其中的items屬於公有屬性,即:無法讓使用者只通過類方法才能獲取到items的值,直接獲取stack.items也是可以被外部訪問到。
三:ES版Stack類私有屬性的封裝
1.偽私有屬性封裝
(1)使用ES6的限定作用域Symbol實現
ES6新增了一種叫作Symbol的基本型別,它是靜態的,不可變的,可以用作物件的屬性。
let _items=Symbol();
class Stack(){
this[_items]=[];
}
注:其他方法就可以讓this[_items]取代this.items即可。
(2)使用該類
之所以被稱為偽私有屬性,因為ES6新增了Object.getOwnPropertySymbols方
法能夠取到類裡面宣告的所有Symbols屬性。即:
let stack=new Stack();
stack.push(5);
stack.push(8);
console.log(stack.this[_items]);//並不能打印出items的內容
//但是
let objectSymbols = Object.getOwnPropertySymbols(stack);
console.log(objectSymbols.length); // 1
console.log(objectSymbols); // [Symbol()]
console.log(objectSymbols[0]); // Symbol()
console.log(stack[objectSymbols[0]]);//就可以直接獲取stack的值,也無法實現讓使用者只能通過方法獲取屬性的意圖。
stack[objectSymbols[0]].push(1);
stack.print(); //輸出 5, 8, 1
2.真私有屬性封裝
(1)使用ES6的WeakMap實現
WeakMap可以儲存鍵值對,其中鍵是物件,值可以是任意資料型別。
const items = new WeakMap();
class Stack {
constructor () {
items.set(this, []); //給棧初始化為[]
}
push(element) {
let s = items.get(this);//獲取棧的內容
s.push(element);
}
pop() {
let s = items.get(this);
let r = s.pop();
return r;
}
//其他方法
}
注:此時我們就不可以在外部直接獲取該私有屬性,但是如果該類檔案內還有此類同級的邏輯使用,那樣我們就可以在同文件下,呼叫到items.get(this),棧的值,那我們需要再封裝一下:
//用一個閉包(外層函式)把Stack類包起來,這樣就只能在這個函式裡訪問WeakMap:
let Stack = (function () {
const items = new WeakMap();
class Stack {
constructor () {
items.set(this, []);
}
//其他方法
}
return Stack; //{5}
})();
注:這樣跟Stack同文件內,類外的呼叫就不可以直接調取到items屬性了,但是這種方法的話:擴充套件類無法繼承私有屬性。所以建議最好棧類檔案裡面只封裝一個類。
四:ES6版Stack類(連結串列)
class Stack{
constructor(){
this.dataStore=[];
this.top=0;
}
push(element){
this.dataStore[this.top++]=element;
}
pop(){
return this.dataStore[--this.top];
}
peek(){
if (this.dataStore[this.top - 1] == undefined) {
return "none"
}
return this.dataStore[this.top-1];
}
length(){
return this.top;
}
clear(){
this.top=0;
}
}
五:棧解決實際問題案例
十進位制轉換為其他進位制
function divideByBase(decNumber,base){
let remStack=new Stack_Array();
let rem;
let binaryString='';
let digits='0123456789ABCDEF';
while(decNumber>0){
rem=Math.floor(decNumber%base);
remStack.push(rem);
decNumber=Math.floor(decNumber/base);
}
while(!remStack.isEmpty()){
binaryString+=digits[remStack.pop()];
}
return binaryString;
}
console.log(divideByBase(15,16));
說明:
base為基數,即二進位制則為:2,八進位制為8,十六進位制為16
decNmuber為十進位制數。