常見數(shù)據(jù)結(jié)構(gòu)的JS實(shí)現(xiàn)(一)

數(shù)據(jù)結(jié)構(gòu)和算法是一位優(yōu)秀的程序員的基本功洞拨。在面試時(shí)這兩點(diǎn)也是考察的重點(diǎn),本文參考《學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法》一書巍耗,總結(jié)了常見的數(shù)據(jù)結(jié)構(gòu)令哟。

目錄:
一、數(shù)組
二屈暗、棧和隊(duì)列
三拆讯、鏈表
四、集合
五养叛、字典和散列表
六种呐、樹
七、圖

內(nèi)容較多弃甥,先介紹前三種數(shù)據(jù)結(jié)構(gòu)爽室。

一、數(shù)組:
幾乎所有的編程語言都原生支持?jǐn)?shù)組類型淆攻,因?yàn)閿?shù)組是最簡單的內(nèi)存數(shù)據(jù)結(jié)構(gòu)阔墩。與其他語言相比嘿架,JavaScript數(shù)組長度和元素類型都是不固定的。并且啸箫,數(shù)組在內(nèi)存空間中也可以不連續(xù)存在耸彪。

1 創(chuàng)建和初始化數(shù)組
JavaScript創(chuàng)建數(shù)組有兩種基本方式:第一種是使用Array構(gòu)造函數(shù),如下面代碼所示:

var colors = new Array();
var colors = new Array(10);  //  創(chuàng)建長度為10的數(shù)組
var colors = new Array('red', 'blue', 'green'); //創(chuàng)建包含'red','blue','green'三個(gè)值的數(shù)組

在使用Array構(gòu)造函數(shù)時(shí)忘苛,可以省略new操作符蝉娜。
第二種是使用數(shù)組字面量表示法,如下代碼所示:

var colors = []; //創(chuàng)建一個(gè)空數(shù)組
var colors = ['red','blue','green]; //創(chuàng)建一個(gè)包含3個(gè)字符串的數(shù)組

2 添加和刪除元素
添加元素到數(shù)組末尾:

var colors = ['red','blue','green'];
colors.push('yellow');
console.log(colors);  //  ["red", "blue", "green", "yellow"]

添加元素到數(shù)組頭部:

var colors = ['red', 'blue', 'green'];
colors.unshift('yellow');
console.log(colors);  //  ["yellow", "red", "blue", "green"]

刪除數(shù)組末尾元素:

var colors = ['red', 'blue', 'green'];
colors.pop();
console.log(colors);  // ["red", "blue"]

刪除數(shù)組頭部元素:

var colors = ['red', 'blue', 'green'];
colors.shift();
console.log(colors);  // ["blue", "green"]

刪除任意位置的元素:
通過數(shù)組提供的splice方法扎唾,可以刪除任意位置的元素召川,如下所示:

var colors = ['red', 'blue', 'green'];
colors.splice(1,1);
console.log(colors);  // ["red", "green"]

3 JavaScript中數(shù)組方法
JavaScript中數(shù)組有很多很強(qiáng)大的方法,大家可以參閱
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array

二胸遇、棧和隊(duì)列:
棧和隊(duì)列也是比較常見的數(shù)據(jù)結(jié)構(gòu)荧呐,是一種遵從后進(jìn)先出(LIFO)原則的有序列表,只能對(duì)棧頂元素進(jìn)行添加或刪除操作狐榔。隊(duì)列是一種遵從先進(jìn)先出(FIFO)原則的有序列表坛增,只能在尾部添加元素,從頭部移除元素薄腻。我們可以通過數(shù)組來實(shí)現(xiàn)棧和隊(duì)列。
1 棧:

棧.PNG

棧需要聲明的方法:
push(element(s)): 添加一個(gè)(或幾個(gè))新元素到棧頂
pop(): 移除棧頂?shù)脑亟彀福瑫r(shí)返回被移除的元素
peek(): 返回棧頂元素
isEmpty(): 棧中是否有元素
clear(): 移除棧中所有元素
size(): 返回棧包含的元素個(gè)數(shù)
下面是棧的實(shí)現(xiàn)方式(構(gòu)造函數(shù)):

function Stack() {
  var items = [];
  this.push= function(element) {
    items.push(element);
  };
  this.pop= function() {
    return items.shift();
  };
  this.peek= function() {
    return items[0];
  };
  this.isEmpty = function() {
    return items.length == 0;
  };
  this.clear = function() {
    items = [];
  };
  this.size= function() {
    return items.length;
  };
}

至此庵楷,便可以通過var newStack = new Stack()的方式聲明一個(gè)棧。
2 隊(duì)列:

隊(duì)列.PNG

隊(duì)列需要聲明的方法:
enqueue(element(s)): 向隊(duì)列尾部添加一個(gè)(或多個(gè))元素
dequeue(): 移除隊(duì)列中的第一個(gè)元素楣颠,并返回該元素
front(): 返回隊(duì)列中的第一個(gè)元素
isEmpty(): 隊(duì)列中是否有元素
clear(): 移除隊(duì)列中所有元素
size(): 返回隊(duì)列包含的元素個(gè)數(shù)
下面是隊(duì)列的實(shí)現(xiàn)方式(構(gòu)造函數(shù)):

function Queue() {
  var items = [];
  this.enqueue = function(element) {
    items.push(element);
  };
  this.dequeue = function() {
    return items.shift();
  };
  this.front = function() {
    return items[0];
  };
  this.isEmpty = function() {
    return items.length == 0;
  };
  this.clear = function() {
    items = [];
  };
  this.size= function() {
    return items.length;
  };
}

同樣尽纽,通過var newQueue = new Queue()的方式聲明一個(gè)隊(duì)列。

三童漩、鏈表:
雖然JavaScript中數(shù)組是動(dòng)態(tài)的弄贿,并且可以在任意位置添加和刪除元素。但其添加和刪除元素的成本仍很高矫膨,需要移除元素差凹。
鏈表中的元素在內(nèi)存中不是連續(xù)放置的。每個(gè)元素由一個(gè)存儲(chǔ)元素本身的節(jié)點(diǎn)和一個(gè)指向下一個(gè)元素的引用組成侧馅。鏈表危尿,仿佛一列火車,一個(gè)元素對(duì)應(yīng)火車的一節(jié)車廂馁痴,元素的指針就像車廂間的連接谊娇。

鏈表.jpg

首先,創(chuàng)建鏈表之前先要?jiǎng)?chuàng)建鏈表中的Node節(jié)點(diǎn)罗晕。因此济欢,需要先聲明Node節(jié)點(diǎn)的構(gòu)造函數(shù)赠堵。Node節(jié)點(diǎn)有兩個(gè)屬性,一個(gè)是element屬性法褥,即要添加到列表的值茫叭,以及一個(gè)next屬性,即指向列表中寫一個(gè)節(jié)點(diǎn)項(xiàng)的指針:

var Node = function (element) {
  this.element = element;
  thie.next = null;
}

鏈表需要聲明的方法:
append(element): 向鏈表尾部添加一個(gè)新的項(xiàng)

  this.append = function(element) {
    var node = new Node(element),
        current;
    if (head === null) { // 判斷鏈表是否為空
      head = node;
    } else {
        current = head;
        while(current.next) { // 遍歷鏈表挖胃,直到最后一個(gè)元素
          current = current.next;
        }
        current.next = node; // 找到最后一個(gè)元素杂靶,將其next設(shè)為node
    }
    length++; // 更新鏈表長度
  };

insert(position, element): 向鏈表的特定位置插入一個(gè)新的項(xiàng)

this.insert = function(position, element) {
  if (position > -1 && position <= length) {
    var node = new Node(element),
        current = head,
        previous,
        index = 0;
    if (position === 0) { //在第一個(gè)位置添加
      node.next = current;
      head = node;
    } else {
        while (index++ < position) {
           previous = current;
           current = current.next;
        }
        node.next = current;
        previous.next = node;
    }
    length++; // 更新鏈表長度
    return true;
  } else {
    return false;
  }
};

removeAt(position): 從鏈表的特定位置移除一項(xiàng)

this.removeAt = function(position) {
// 檢查是否越界
  if (position > -1 && position < length) {
    var current = head,
        previous,
        index = 0;
// 移除第一項(xiàng)
    if (position === 0) {
        head = current.next;
    } else {
        while (index++ < position) {
          previous = current;
          current = current.next;
        }
        // 將previous與current的下一項(xiàng)連接起來
        previous.next = current.next;
      }
    length--;
    return current.element;
} else {
    return null;
  }
};

indexOf(element): 返回元素在鏈表中的索引。如果鏈表中沒有該元素則返回-1

this.indexOf = function(element) {
  var current = head,
      index = 0;
  while (current) {
    if (element === current.element) {
      return index;
    }
    index++;
    current = current.next;
  }
  return -1;
};

remove(element): 從鏈表中移除一項(xiàng)

this.remove = function(element) {
  var index = this.indexOf(element);
   return this.removeAt(index);
};

isEmpty(): 鏈表是否為空

this.isEmpty = function () {
  return length === 0;
};

size(): 鏈表中包含元素的個(gè)數(shù)

this.size = function () {
  return length;
};

鏈表有多種不同的類型酱鸭,這邊介紹兩種常見的: 雙向鏈表循環(huán)鏈表
雙向鏈表:雙向鏈表與普通鏈表的區(qū)別在于吗垮,雙向鏈表的鏈接是雙向的:一個(gè)鏈向下一個(gè)元素,另一個(gè)鏈向前一個(gè)元素凹髓,如下圖所示:

雙向鏈表.jpg

循環(huán)鏈表:最后一個(gè)元素指向下一個(gè)元素的指針不是引用null烁登,而是第一個(gè)元素,如下圖所示:
循環(huán)鏈表.jpg

至此蔚舀,數(shù)組饵沧、隊(duì)列、棧和鏈表介紹完畢赌躺。剩下的四個(gè)數(shù)據(jù)結(jié)構(gòu)下回分曉~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末狼牺,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子礼患,更是在濱河造成了極大的恐慌是钥,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缅叠,死亡現(xiàn)場離奇詭異悄泥,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)肤粱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門弹囚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人领曼,你說我怎么就攤上這事鸥鹉。” “怎么了悯森?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵宋舷,是天一觀的道長。 經(jīng)常有香客問我瓢姻,道長祝蝠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮绎狭,結(jié)果婚禮上细溅,老公的妹妹穿的比我還像新娘。我一直安慰自己儡嘶,他們只是感情好喇聊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蹦狂,像睡著了一般誓篱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凯楔,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天窜骄,我揣著相機(jī)與錄音,去河邊找鬼摆屯。 笑死邻遏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的虐骑。 我是一名探鬼主播准验,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼廷没!你這毒婦竟也來了糊饱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤颠黎,失蹤者是張志新(化名)和其女友劉穎济似,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盏缤,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年蓖扑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了唉铜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡律杠,死狀恐怖潭流,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情柜去,我是刑警寧澤灰嫉,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站嗓奢,受9級(jí)特大地震影響讼撒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一根盒、第九天 我趴在偏房一處隱蔽的房頂上張望钳幅。 院中可真熱鬧,春花似錦炎滞、人聲如沸敢艰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钠导。三九已至,卻和暖如春森瘪,著一層夾襖步出監(jiān)牢的瞬間牡属,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國打工柜砾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留湃望,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓痰驱,卻偏偏與公主長得像证芭,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子担映,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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