JS鏈你弦、表

一惊豺、鏈表數(shù)據(jù)結(jié)構(gòu)

要存儲多個元素,數(shù)組(或列表)可能是最常用的數(shù)據(jù)結(jié)構(gòu)禽作。然而這種數(shù)據(jù)結(jié)構(gòu)有一個缺點(diǎn)尸昧,數(shù)字的大小是固定的,從數(shù)組的起點(diǎn)或中間插入或移除項(xiàng)的成本很高旷偿,因?yàn)樾枰苿釉亍?br> 鏈表存儲有序的元素集合烹俗,但不用于數(shù)組爆侣,鏈表中的元素在內(nèi)存中并不是連續(xù)放置的。每個元素由一個存儲元素本身的節(jié)點(diǎn)和一個指向下一個元素的飲用(也稱指針或鏈接)組成衷蜓。下圖展示了一個鏈表的結(jié)構(gòu)


image.png

相對于傳統(tǒng)的數(shù)組累提,鏈表的一個好處在于,添加或移動元素的時候不需要移動其他元素磁浇。然而斋陪,鏈表需要使用指針,因此實(shí)現(xiàn)鏈表時需要額外注意置吓。數(shù)組的一個細(xì)節(jié)是可以直接訪問任何位置的元素无虚,而想要訪問鏈表中間的一個元素,需要從起點(diǎn)(表頭)開始迭代列表直到找到所需的元素衍锚。
舉幾個形象的例子來形容:

  • 尋寶游戲:你有一條線索友题,這條線索是指向?qū)ふ蚁乱粭l線索的地點(diǎn)的指針。你順著這條鏈接去下一個地點(diǎn)戴质,得到另一條指向再下一處的線索度宦。得到列表中間的線索的唯一辦法,就是從起點(diǎn)(第一條線索)順著列表尋找
  • 火車:一列火車是由一系列車廂組成告匠,每節(jié)車廂相互連接戈抄,你很容易分離一節(jié)車皮,改變它的位置后专,添加或者移除它划鸽,車廂之間的連接就是指針
特點(diǎn)
  • 鏈表是多個元素組成的列表
  • 元素存儲不連續(xù),用next指針連接到一起
  • JS中沒有鏈表戚哎,但是可以用Object模擬鏈表

二裸诽、創(chuàng)建鏈表

下面我們實(shí)現(xiàn)一個鏈表類,并給他加點(diǎn)方法

class Node {  //節(jié)點(diǎn)類
    //構(gòu)造函數(shù)
    constructor(item) { 
        this.item = item;
        this.next = null;
    }
}
class LinkedList {  // 鏈表類
    //構(gòu)造函數(shù)
    constructor() { 
        this.head = null;
        this.length = 0;
    }
    //新增節(jié)點(diǎn)
    append(item) { 
        let node = new Node(item);
        let current; //暫存當(dāng)前位置
        if(this.head === null) { // 如果頭結(jié)點(diǎn)為空,當(dāng)前節(jié)點(diǎn)作為頭結(jié)點(diǎn)
            this.head = node;
        } else { 
            current = this.head;
            while(current.next) {     //遍歷找到鏈表尾部
                current = current.next;
            }
            current.next = node;    //在鏈表尾部加入新節(jié)點(diǎn)
        }
        this.length++; //更新鏈表長度
    }
    //刪除節(jié)點(diǎn),并獲得刪除節(jié)點(diǎn)的值
    remove(index) { 
        if(index > -1 && index < this.length) { //預(yù)防下標(biāo)越界
            var current = this.head;//暫存當(dāng)前位置
            var previous; //暫存當(dāng)前位置的前一個
            var position = 0;
            if(index === 0) {  //要刪除的是第一個位置型凳,就得改變頭指針指向
                this.head = current.next;
            } else { 
                while(position++ < index) { //遍歷直到current處于index位置
                    previous = current;
                    current = current.next;  //此時current處于index處,previous在index-1處
                }
                previous.next = current.next; //改變鏈表結(jié)構(gòu),跳過index處
            }
            this.length--; //更新鏈表長度
            return current.[圖片上傳中...(image.png-aecada-1661950439992-0)]
; //返回index處的值
        } else { 
            return null;    //下標(biāo)越界返回空
        }
    }
    //插入節(jié)點(diǎn)
    insert(index, item) {
        if(index > -1 && index <= this.length) { 
            let node = new Node(item);
            let current = this.head;
            let previous;
            let position = 0;
            if(index === 0) { 
                node.next = current;
                this.head = node;
            } else { 
                while(position++ < index) { 
                    previous = current;
                    current = current.next;
                }
                node.next = current;
                previous.next = node;
            }
            length++;
            return true; //插入成功
        } else { 
            return false; //插入失敗
        }
    }
    //獲取索引
    indexOf(item) { 
        let current = this.head;
        let position = 0;
        while(current) { 
            if(current.item === item) { 
                return position;
            }
            position++;
            current = current.next;
        }
        return -1; //未找到索引
    }
    //將鏈表轉(zhuǎn)換成字符串
    toString() { 
        let current = this.head;
        let string = '';
        while(current) { 
            string += current.item + ((current.next ? ',': ''));
            current = current.next;
        }
        return string;
    }
    //鏈表長度
    size() { 
        return this.length;
    }
    //判斷鏈表是否為空
    isEmpty() { 
        return this.length === 0;
    }
}

這樣我們就實(shí)現(xiàn)了一個鏈表類丈冬,我們也為其添加了很多自定義方法

  • 新增節(jié)點(diǎn) append
  • 刪除節(jié)點(diǎn) remove
  • 插入節(jié)點(diǎn) insert
  • 獲取索引 indexOf
  • 鏈表轉(zhuǎn)字符串 toString
  • 獲取鏈表長度 size
  • 判斷鏈表是否為空 isEmpty

未完待續(xù)......

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市啰脚,隨后出現(xiàn)的幾起案子殷蛇,更是在濱河造成了極大的恐慌,老刑警劉巖橄浓,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粒梦,死亡現(xiàn)場離奇詭異,居然都是意外死亡荸实,警方通過查閱死者的電腦和手機(jī)匀们,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來准给,“玉大人泄朴,你說我怎么就攤上這事重抖。” “怎么了祖灰?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵钟沛,是天一觀的道長。 經(jīng)常有香客問我局扶,道長恨统,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任三妈,我火速辦了婚禮畜埋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘畴蒲。我一直安慰自己悠鞍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布模燥。 她就那樣靜靜地躺著咖祭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蔫骂。 梳的紋絲不亂的頭發(fā)上心肪,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天,我揣著相機(jī)與錄音纠吴,去河邊找鬼。 笑死慧瘤,一個胖子當(dāng)著我的面吹牛戴已,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锅减,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼糖儡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了怔匣?” 一聲冷哼從身側(cè)響起握联,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎每瞒,沒想到半個月后金闽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡剿骨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年代芜,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浓利。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡挤庇,死狀恐怖钞速,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嫡秕,我是刑警寧澤渴语,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站昆咽,受9級特大地震影響驾凶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜潮改,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一狭郑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧汇在,春花似錦翰萨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至阿蝶,卻和暖如春雳锋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背羡洁。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工玷过, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人筑煮。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓辛蚊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親真仲。 傳聞我的和親對象是個殘疾皇子袋马,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

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