數(shù)據(jù)結(jié)構(gòu)與算法(1) - 棧

前言:為什么要學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)

  1. 編程語言是相通的
    人們常說,編程語言是相通的,學(xué)會了一門析孽,其他語言也可以很輕松的掌握,我認為這是一個似是而非的說法只怎。
    每一門編程語言都離不開變量,條件判斷怜俐,循環(huán)這些概念身堡,但是每門編程語言又有自己的使用范圍,都有自己所擅長的領(lǐng)域拍鲤。即便nodejs已經(jīng)可以一統(tǒng)前后端贴谎,也總有他不能勝任的工作
    多年的工作經(jīng)驗告訴我汞扎,相通的不是語言,而是數(shù)據(jù)結(jié)構(gòu)與算法
  2. 學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)的目標
  • 提高算法能力
  • 提高程序框架設(shè)計能力
  • 供你面試裝逼(這點真的沒毛病擅这,尤其是前端面試)
  1. 學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)需要的知識儲備
    我覺得你需要非常熟練的使用數(shù)組這個數(shù)據(jù)類型澈魄,再一個去知道如何在js中定義一個類。這里推薦下阮一峰老師的一篇文章Javascript定義類的三種方法仲翎。接下來我將以我粗淺的認識與大家一起學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法

數(shù)據(jù)結(jié)構(gòu)之 -- 棧

1. 棧的定義

棧是一種特殊的線性表痹扇,僅能夠在棧頂進行操作,有先進后出(后進先出)的特點


棧.png

這里可以給大家聚一下生活中的例子溯香,對大家對棧的理解有很大的幫助鲫构。玩羽毛球的同學(xué)有時會買一桶羽毛球,而這個羽毛球桶就是典型的棧結(jié)構(gòu)
羽毛球.jpeg

2. 棧的實現(xiàn)

2.1 數(shù)據(jù)存儲

從數(shù)據(jù)存儲的角度看玫坛,要實現(xiàn)棧有兩種方式结笨,一種是以數(shù)組做基礎(chǔ),一種是以鏈表為基礎(chǔ)湿镀。數(shù)組是最簡單的實現(xiàn)方式炕吸,鏈表在后面會作為單獨的一種數(shù)據(jù)結(jié)構(gòu)來講解
我們先來定一個一個簡單的Stack類

function Stack() {
  var items = []; // 使用數(shù)組存儲數(shù)據(jù)
}
2.2 棧的方法

棧有以下幾個方法

  • push 添加一個元素到棧頂(向桶里放入一個羽毛球)
  • pop 彈出棧頂元素(從桶里拿出一個羽毛球)
  • top 返回棧頂還俗,注意勉痴,不是彈出(看一眼不拿)
  • isEmpty 判斷棧是否為空
  • size 返回棧內(nèi)元素的個數(shù)
  • clear 清空棧
    接下來赫模,我們逐一實現(xiàn)這些方法
2.2.1 push方法
// push方法向棧里壓入一個元素
this.push = function(item) {
  items.push(item)
}
2.2.2 pop方法
// pop方法把棧頂元素彈出
this.pop = function() {
  return items.pop()
}
2.2.3 top方法
// top方法返回棧頂元素
this.top = function() {
  return items[items.length - 1]
}
2.2.4 isEmpty方法
// isEmpty方法判斷棧是否為空
this.isEmpty = function() {
  return items.length == 0;
}
2.2.5 size方法
// size方法返回棧內(nèi)元素的個數(shù)
this.size = function() {
  return items.length
}
2.2.6 clear方法
// clear方法清空棧
this.clear = function() {
  items = []
}

最終完整版如下

function Stack() {
    var items = [];  // 使用數(shù)組存儲數(shù)據(jù)

    // push方法向棧里壓入一個元素
    this.push = function(item){
        items.push(item);
    };

    // pop方法把棧頂?shù)脑貜棾?    this.pop = function(){
        return items.pop();
    };

    // top 方法返回棧頂元素
    this.top = function(){
        return items[items.length - 1];
    };

    // isEmpty返回棧是否為空
    this.isEmpty = function(){
        return items.length == 0;
    };

    // size方法返回棧的大小
    this.size = function(){
        return items.length;
    };

    // clear 清空棧
    this.clear = function(){
        items = []
    }
}
2.3 被欺騙的感覺

看完上面的實現(xiàn),很多同學(xué)會說蚀腿,佑弟你騙我嘴瓤,說的那么神乎其神的數(shù)據(jù)結(jié)構(gòu),這里的棧竟然就是對數(shù)組進行了一層封裝而已袄蚋啤廓脆!WTF
真的是只做了一層封裝嗎?請大家思考以下問題

  1. 給你一個數(shù)組磁玉,你可以通過索引操作任意元素停忿,但是給你一個棧,你能操作棧內(nèi)任意元素嗎蚊伞,棧提供的方法只允許我們操作棧頂元素席赂,也就是數(shù)組的最后一個元素,這種限制其實提供給我們一種思考問題的方式时迫,這個方式也就是棧的特性颅停,后進先出。
  2. 既然實現(xiàn)棧用的是數(shù)組掠拳,那棧能做的事情癞揉,數(shù)組也一樣可以做,為什么要多此一舉弄個棧出來?封裝是為了隱藏實現(xiàn)細節(jié)喊熟,有時候站在棧的角度思考問題比站在數(shù)組的角度思考問題更加方便柏肪,后面的練習(xí)你就會有所體會

3. 棧的應(yīng)用練習(xí)

在這里我們通過一個練習(xí)題,你就能明白我剛才所說的站在棧的肩膀上思考問題有時候比站在數(shù)組的肩膀上思考問題更加方便

3.1 括號的合法
3.1.1 題目要求

下面的字符串中包含小括號芥牌,請便攜一個函數(shù)判斷字符串中的括號是否合法烦味,所謂的合法就是括號是成對出現(xiàn)

((ab(cd)g(aa))(cc))   合法
(ab(cd))(bbdsf)(1    不合法
3.1.2 思路分析

括號存在嵌套關(guān)系,也存在并列關(guān)系壁拉,如果使用數(shù)組存儲這些括號谬俄,再想辦法一一匹配左右括號似乎是一個可行的辦法,可是如何判斷一個左括號對應(yīng)的是哪個右括號呢扇商?
現(xiàn)在凤瘦,我們站在棧的肩膀上去思考這個問題,解題的過程就非常簡單了案铺,我們可以遍歷這個字符串蔬芥,對每個字符做以下操作

  • 遇到左括號,就把左括號壓入棧頂
  • 遇到右括號控汉,判斷棧是否為空笔诵,為空則說明沒有與之對應(yīng)的左括號,不合法姑子,如果不為空乎婿,則將棧頂元素彈出,這對括號就抵消了
    當for循環(huán)結(jié)束后街佑,如果棧為空谢翎,則說明左右括號全部抵消,則合法沐旨,反之不合法
3.1.3 示例代碼
function isLegitimate(string){
    var stack = new Stack();
    for(var i=0; i<string.length; i++ ){
        var item = string[i];
        if(item == "("){
            // 將左括號壓入棧
            stack.push(item);
        }else if (item==")"){
            // 如果為空,就說明沒有左括號與之抵消
            if(stack.isEmpty()){
                return false;
            }else{
                // 將棧頂?shù)脑貜棾?                stack.pop();
            }
        }

    }
    return stack.size() == 0;
};
console.log(isLegitimate("((ab(cd)g(aa))(cc))"))
console.log(isLegitimate("(ab(cd))(bbdsf)(1"))
3.1.4 小結(jié)

棧的底層是不是使用了數(shù)組不重要森逮,重要的是棧的后進先出的特性,重要的是你只能操作棧頂元素磁携,一定要忽略底層如何實現(xiàn)褒侧,去關(guān)心棧的特性。
在我們寫代碼的時候谊迄,經(jīng)常進行回退的操作闷供,control+z就可以了,那你有沒有想過统诺,這個就可以用棧來實現(xiàn)歪脏,每一步都放到棧中,當你想回退的時候粮呢,將棧頂元素彈出唾糯,你就得到了你之前一步的操作

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怠硼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子移怯,更是在濱河造成了極大的恐慌,老刑警劉巖这难,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舟误,死亡現(xiàn)場離奇詭異,居然都是意外死亡姻乓,警方通過查閱死者的電腦和手機嵌溢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹋岩,“玉大人赖草,你說我怎么就攤上這事〖舾觯” “怎么了秧骑?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長扣囊。 經(jīng)常有香客問我乎折,道長,這世上最難降的妖魔是什么侵歇? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任骂澄,我火速辦了婚禮,結(jié)果婚禮上惕虑,老公的妹妹穿的比我還像新娘坟冲。我一直安慰自己,他們只是感情好溃蔫,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布健提。 她就那樣靜靜地躺著,像睡著了一般酒唉。 火紅的嫁衣襯著肌膚如雪矩桂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天痪伦,我揣著相機與錄音侄榴,去河邊找鬼相种。 笑死之众,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的著蛙。 我是一名探鬼主播辉哥,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼桦山,長吁一口氣:“原來是場噩夢啊……” “哼攒射!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恒水,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤会放,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后钉凌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咧最,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年御雕,在試婚紗的時候發(fā)現(xiàn)自己被綠了矢沿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡酸纲,死狀恐怖捣鲸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闽坡,我是刑警寧澤栽惶,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站无午,受9級特大地震影響媒役,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜宪迟,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一酣衷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧次泽,春花似錦穿仪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至玖像,卻和暖如春紫谷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背捐寥。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工笤昨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人握恳。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓瞒窒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親乡洼。 傳聞我的和親對象是個殘疾皇子崇裁,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容