成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

javascript的數(shù)據(jù)結(jié)構(gòu)--實(shí)現(xiàn)一個(gè)棧

defcon / 2048人閱讀

摘要:棧不管是在哪個(gè)語(yǔ)言,,還有咱們的都有這個(gè)數(shù)據(jù)結(jié)構(gòu),很多從別的行業(yè)轉(zhuǎn)開(kāi)發(fā)的朋友都會(huì)經(jīng)過(guò)這個(gè)學(xué)習(xí)過(guò)程。新添加的或待刪除的元素都保存在棧的同一端,稱作棧頂,另一端就叫棧底。移除棧頂?shù)脑?,同時(shí)返回被移除的元素。

棧:不管是在哪個(gè)語(yǔ)言,c/c++,java,python,還有咱們的javascript都有這個(gè)數(shù)據(jù)結(jié)構(gòu),很多從別的行業(yè)轉(zhuǎn)開(kāi)發(fā)的朋友都會(huì)經(jīng)過(guò)這個(gè)學(xué)習(xí)過(guò)程。

棧:一種遵從后進(jìn)先出(LIFO)原則的有序集合。新添加的或待刪除的元素都保存在棧的
同一端,稱作棧頂,另一端就叫棧底。在棧里,新元素都靠近棧頂,舊元素都接近棧底。

在現(xiàn)實(shí)生活中也能發(fā)現(xiàn)很多棧的例子。例如,下圖里的一摞書(shū)或者餐廳里堆放的盤子。
棧也被用在編程語(yǔ)言的編譯器和內(nèi)存中保存變量、方法調(diào)用等。

創(chuàng)建一個(gè)棧 (直接用ES6的class來(lái)寫(xiě)吧)

先熟悉一下棧的一些方法:

push(element(s)) :添加一個(gè)(或幾個(gè))新元素到棧頂。
pop() :移除棧頂?shù)脑?,同時(shí)返回被移除的元素。
peek() :返回棧頂?shù)脑?,不?duì)棧做任何修改(這個(gè)方法不會(huì)移除棧頂?shù)脑?,僅僅返回它)。
isEmpty() :如果棧里沒(méi)有任何元素就返回 true ,否則返回 false 。
clear() :移除棧里的所有元素。
size() :返回棧里的元素個(gè)數(shù)。這個(gè)方法和數(shù)組的 length 屬性很類似。
class Stack {
    constructor () {
        this.items = []; //{1}
    }
    push(element) {
        this.items.push(element);
    }
    pop() {
        this.items.pop();
    }
    peek() {
        return items[items.length-1];
    }
    isEmpty() {
        return items.length == 0;
    }
    size() {
        return items.length;
    }
    clear() {
        items = [];
    }
    print() {
        console.log(items);
    }
}

盡管代碼看起來(lái)更簡(jiǎn)潔、更漂亮,變量 items 卻是公共的。ES6的類是基于原型的。雖然基
于原型的類比基于函數(shù)的類更節(jié)省內(nèi)存,也更適合創(chuàng)建多個(gè)實(shí)例,卻不能夠聲明私有屬性(變量)
或方法。而且,在這種情況下,我們希望 Stack 類的用戶只能訪問(wèn)暴露給類的方法。否則,就有
可能從棧的中間移除元素(因?yàn)槲覀冇脭?shù)組來(lái)存儲(chǔ)其值),這不是我們希望看到的。

1. 用ES6的限定作用域 Symbol 實(shí)現(xiàn)類

ES6新增了一種叫作 Symbol 的基本類型,它是不可變的,可以用作對(duì)象的屬性??纯丛趺从?br>它來(lái)在 Stack 類中聲明 items 屬性:

let _items = Symbol(); //{1}
class Stack {
    constructor () {
        this[_items] = []; //{2}
    }
    //Stack方法
}

在上面的代碼中,我們聲明了 Symbol 類型的變量 _items (行 {1} ),在類的 constructor 函
數(shù)中初始化它的值(行 {2} )。要訪問(wèn) _items ,只需把所有的 this.items 都換成 this[_items] 。
這種方法創(chuàng)建了一個(gè)假的私有屬性,因?yàn)镋S6新增的 Object.getOwnPropertySymbols 方
法能夠取到類里面聲明的所有 Symbols 屬性。下面是一個(gè)破壞 Stack 類的例子:

let stack = new Stack();
stack.push(5);
stack.push(8);
let objectSymbols = Object.getOwnPropertySymbols(stack);
console.log(objectSymbols.length); // 1
console.log(objectSymbols); // [Symbol()]
console.log(objectSymbols[0]); // Symbol()
stack[objectSymbols[0]].push(1);
stack.print(); // 輸出 5, 8, 1

從以上代碼可以看到,訪問(wèn) stack[objectSymbols[0]] 是可以得到 _items 的。并且,
_items 屬性是一個(gè)數(shù)組,可以進(jìn)行任意的數(shù)組操作,比如從中間刪除或添加元素。我們操作的
是棧,不應(yīng)該出現(xiàn)這種行為。

2. 用ES6的 WeakMap 實(shí)現(xiàn)類

有一種數(shù)據(jù)類型可以確保屬性是私有的,這就是 WeakMap 。我們會(huì)在第7章深入探討 Map 這
種數(shù)據(jù)結(jié)構(gòu),現(xiàn)在只需要知道 WeakMap 可以存儲(chǔ)鍵值對(duì),其中鍵是對(duì)象,值可以是任意數(shù)據(jù)類型。

如果用 WeakMap 來(lái)存儲(chǔ) items 變量, Stack 類就是這樣的:

const items = new WeakMap(); //{1}
class Stack {
    constructor () {
        items.set(this, []); //{2}
    }
    push(element) {
        let s = items.get(this); //{3}
        s.push(element);
    }
    pop() {
        let s = items.get(this);
        let r = s.pop();
        return r;
    }
    //其他方法
}

行 {1} ,聲明一個(gè) WeakMap 類型的變量 items 。
行 {2} ,在 constructor 中,以 this ( Stack 類自己的引用)為鍵,把代表?xiàng)5臄?shù)組存入 items。
行 {3} ,從 WeakMap 中取出值,即以 this 為鍵(行 {2} 設(shè)置的)從 items 中取值。
現(xiàn)在我們知道, items 在 Stack 類里是真正的私有屬性了,但還有一件事要做。 items 現(xiàn)在
仍然是在 Stack 類以外聲明的,因此誰(shuí)都可以改動(dòng)它。我們要用一個(gè)閉包(外層函數(shù))把 Stack
類包起來(lái),這樣就只能在這個(gè)函數(shù)里訪問(wèn) WeakMap :

let Stack = (function () {
    const items = new WeakMap();
    class Stack {
        constructor () {
            items.set(this, []);
        }
        //其他方法
    }
    return Stack; //{4}
})();

當(dāng) Stack 函數(shù)里的構(gòu)造函數(shù)被調(diào)用時(shí),會(huì)返回 Stack 類的一個(gè)實(shí)例(行 {4} )。

一個(gè)例子(把十進(jìn)制的數(shù)轉(zhuǎn)換成任意進(jìn)制的數(shù))

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

我們只需要改變一個(gè)地方。在將十進(jìn)制轉(zhuǎn)成二進(jìn)制時(shí),余數(shù)是0或1;在將十進(jìn)制轉(zhuǎn)成八進(jìn)制
時(shí),余數(shù)是0到7之間的數(shù);但是將十進(jìn)制轉(zhuǎn)成16進(jìn)制時(shí),余數(shù)是0到9之間的數(shù)字加上A、B、C、
D、E和F(對(duì)應(yīng)10、11、12、13、14和15)。因此,我們需要對(duì)棧中的數(shù)字做個(gè)轉(zhuǎn)化才可以(行
{5} 和行 {6} )。

參考:《Javascript數(shù)據(jù)結(jié)構(gòu)與算法》

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/99367.html

相關(guān)文章

  • JavaScript數(shù)據(jù)結(jié)構(gòu)

    摘要:我們都知道數(shù)組是里面比較常用的一種數(shù)據(jù)結(jié)構(gòu),棧和數(shù)組類似,定義如下棧是一種遵從后進(jìn)先出原則的有序集合。新增加和待刪除的元素都保存在棧的尾部,也稱棧頂,相反的另一端就叫棧底,在棧的這種數(shù)據(jù)結(jié)構(gòu)里面,我們新增的元素都在棧頂,舊的元素都在棧底。 由于不是計(jì)算機(jī)專業(yè)出身,對(duì)數(shù)據(jù)結(jié)構(gòu)這些了解的比較少,最近看了一些相關(guān)的書(shū)籍,這里做一些總結(jié)。本篇要說(shuō)的是棧。我們都知道數(shù)組是JavaScript里面...

    nanchen2251 評(píng)論0 收藏0
  • Javascript實(shí)現(xiàn)基本數(shù)據(jù)結(jié)構(gòu)

    摘要:今天實(shí)現(xiàn)的是最基本的數(shù)據(jù)結(jié)構(gòu)之一棧棧在中有著非常重要,基本類型會(huì)存儲(chǔ)在棧中,你可以操作實(shí)際的值。要定義一個(gè)棧,首先需要明白,棧的基本結(jié)構(gòu)有哪些,需要遵循哪些規(guī)則。首先創(chuàng)建一個(gè)函數(shù)對(duì)象表示棧。 Javascript工程師,總會(huì)面對(duì)一個(gè)問(wèn)題,數(shù)據(jù)結(jié)構(gòu)和算法會(huì)成為自己的短板,不僅是對(duì)非科班,甚至一些科班出身的工程師來(lái)說(shuō)也是自己的短板,于是就有了這系列文章。基礎(chǔ)決定深度,前端入門易,上升困難,...

    seanlook 評(píng)論0 收藏0
  • Javascript實(shí)現(xiàn)基本數(shù)據(jù)結(jié)構(gòu)

    摘要:今天實(shí)現(xiàn)的是最基本的數(shù)據(jù)結(jié)構(gòu)之一棧棧在中有著非常重要,基本類型會(huì)存儲(chǔ)在棧中,你可以操作實(shí)際的值。要定義一個(gè)棧,首先需要明白,棧的基本結(jié)構(gòu)有哪些,需要遵循哪些規(guī)則。首先創(chuàng)建一個(gè)函數(shù)對(duì)象表示棧。 Javascript工程師,總會(huì)面對(duì)一個(gè)問(wèn)題,數(shù)據(jù)結(jié)構(gòu)和算法會(huì)成為自己的短板,不僅是對(duì)非科班,甚至一些科班出身的工程師來(lái)說(shuō)也是自己的短板,于是就有了這系列文章?;A(chǔ)決定深度,前端入門易,上升困難,...

    cnio 評(píng)論0 收藏0
  • 學(xué)習(xí)javascript數(shù)據(jù)結(jié)構(gòu)(一)——和隊(duì)列

    摘要:原文地址學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)一棧和隊(duì)列博主博客地址的個(gè)人博客幾乎所有的編程語(yǔ)言都原生支持?jǐn)?shù)組類型,因?yàn)閿?shù)組是最簡(jiǎn)單的內(nèi)存數(shù)據(jù)結(jié)構(gòu)。他們就是棧和隊(duì)列。我們稱作棧頂,而另一端我們稱作棧底。移除棧頂?shù)脑?,同時(shí)返回被移除元素。 前言 只要你不計(jì)較得失,人生還有什么不能想法子克服的。 原文地址:學(xué)習(xí)javascript數(shù)據(jù)結(jié)構(gòu)(一)——棧和隊(duì)列 博主博客地址:Damonare的個(gè)人博客 幾乎所有的編程...

    doodlewind 評(píng)論0 收藏0
  • 學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(一):與隊(duì)列

    摘要:之?dāng)?shù)組操作接下來(lái)就是數(shù)據(jù)結(jié)構(gòu)的第一部分,棧。以字符串顯示棧中所有內(nèi)容方法的實(shí)現(xiàn)說(shuō)明需要往棧中添加新元素,元素位置在隊(duì)列的末尾。的前端樂(lè)園原文鏈接寒假前端學(xué)習(xí)學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法,棧與隊(duì)列 本系列的第一篇文章: 學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(一),棧與隊(duì)列第二篇文章:學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(二):鏈表第三篇文章:學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(三):集合第...

    Flink_China 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<