摘要:就那么回事后記說到現(xiàn)在一直都是線性表,就是順序數(shù)據(jù)結(jié)構(gòu),他們都是有順序的,數(shù)據(jù)都是一條繩子上的螞蚱。那么,如果數(shù)據(jù)是沒有順序的呢那又該使用哪種數(shù)據(jù)結(jié)構(gòu)呢這個放到學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)三集合中學(xué)習(xí)。
前言
人生總是直向前行走,從不留下什么。
原文地址:學(xué)習(xí)javascript數(shù)據(jù)結(jié)構(gòu)(二)——鏈表
博主博客地址:Damonare的個人博客
正文 鏈表簡介????上一篇博客-學(xué)習(xí)javascript數(shù)據(jù)結(jié)構(gòu)(一)——棧和隊列說了棧和隊列在javascript中的實現(xiàn),我們運用javascript提供的API很容易的實現(xiàn)了棧和隊列,但這種數(shù)據(jù)結(jié)構(gòu)有一個很明顯的缺點,因為數(shù)組大小是固定的所以我們在移除或是添加一項數(shù)據(jù)的時候成本很高,基本都需要吧數(shù)據(jù)重排一次。(javascript的Array類方法雖然很方便但背后的原理同樣是這樣的)
????相比數(shù)組我們今天主角——鏈表就要來的隨性的多,簡單的理解可以是這樣:在內(nèi)存中,棧和隊列(數(shù)組)的存在就是一個整體,如果想要對她內(nèi)部某一個元素進(jìn)行移除或是添加一個新元素就要動她內(nèi)部所有的元素,所謂牽一發(fā)而動全身;而鏈表則不一樣,每一個元素都是由元素本身數(shù)據(jù)和指向下一個元素的指針構(gòu)成,所以添加或是移除某一個元素不需要對鏈表整體進(jìn)行操作,只需要改變相關(guān)元素的指針指向就可以了。
????鏈表在實際生活中的例子也有很多,比如自行車的鏈條,環(huán)環(huán)相扣,但添加或是移除某一個環(huán)節(jié)只需要對癥下藥,對相關(guān)環(huán)節(jié)進(jìn)行操作就OK。再比如:火車,火車就是一個鏈表,每一節(jié)車廂就是元素,想要移除或是添加某一節(jié)車廂,只需要把連接車廂的鏈條改變一下就好了。那么,在javascript中又該怎么去實現(xiàn)鏈表結(jié)構(gòu)呢?
鏈表的創(chuàng)建首先我們要創(chuàng)建一個鏈表類:
function LinkedList(){ //各種屬性和方法的聲明 }
然后我們需要一種數(shù)據(jù)結(jié)構(gòu)來保存鏈表里面的數(shù)據(jù):
var Node=function(element){ this.element=element; this.next=null; } //Node類表示要添加的元素,他有兩個屬性,一個是element,表示添加到鏈表中的具體的值;另一個是next,表示要指向鏈表中下一個元素的指針。
接下來,我們需要給鏈表聲明一些方法:
append(element):向鏈表尾部添加一個新的元素;
insert(position,element):向鏈表特定位置插入元素;
remove(element):從鏈表移除一項;
indexOf(element):返回鏈表中某元素的索引,如果沒有返回-1;
removeAt(position):從特定位置移除一項;
isEmpty():判斷鏈表是否為空,如果為空返回true,否則返回false;
size():返回鏈表包含的元素個數(shù);
toString():重寫繼承自O(shè)bject類的toString()方法,因為我們使用了Node類;
鏈表的完整代碼:function LinkedList() { //Node類聲明 let Node = function(element){ this.element = element; this.next = null; }; //初始化鏈表長度 let length = 0; //初始化第一個元素 let head = null; this.append = function(element){ //初始化添加的Node實例 let node = new Node(element), current; if (head === null){ //第一個Node實例進(jìn)入鏈表,之后在這個LinkedList實例中head就不再是null了 head = node; } else { current = head; //循環(huán)鏈表知道找到最后一項,循環(huán)結(jié)束current指向鏈表最后一項元素 while(current.next){ current = current.next; } //找到最后一項元素后,將他的next屬性指向新元素node,j建立鏈接 current.next = node; } //更新鏈表長度 length++; }; this.insert = function(position, element){ //檢查是否越界,超過鏈表長度或是小于0肯定不符合邏輯的 if (position >= 0 && position <= length){ let node = new Node(element), current = head, previous, index = 0; if (position === 0){ //在第一個位置添加 node.next = current; head = node; } else { //循環(huán)鏈表,找到正確位置,循環(huán)完畢,previous,current分別是被添加元素的前一個和后一個元素 while (index++ < position){ previous = current; current = current.next; } node.next = current; previous.next = node; } //更新鏈表長度 length++; return true; } else { return false; } }; this.removeAt = function(position){ //檢查是否越界,超過鏈表長度或是小于0肯定不符合邏輯的 if (position > -1 && position < length){ let current = head, previous, index = 0; //移除第一個元素 if (position === 0){ //移除第一項,相當(dāng)于head=null; head = current.next; } else { //循環(huán)鏈表,找到正確位置,循環(huán)完畢,previous,current分別是被添加元素的前一個和后一個元素 while (index++ < position){ previous = current; current = current.next; } //鏈接previous和current的下一個元素,也就是把current移除了 previous.next = current.next; } length--; return current.element; } else { return null; } }; this.indexOf = function(element){ let current = head, index = 0; //循環(huán)鏈表找到元素位置 while (current) { if (element === current.element) { return index; } index++; current = current.next; } return -1; }; this.remove = function(element){ //調(diào)用已經(jīng)聲明過的indexOf和removeAt方法 let index = this.indexOf(element); return this.removeAt(index); }; this.isEmpty = function() { return length === 0; }; this.size = function() { return length; }; this.getHead = function(){ return head; }; this.toString = function(){ let current = head, string = ""; while (current) { string += current.element + (current.next ? ", " : ""); current = current.next; } return string; }; this.print = function(){ console.log(this.toString()); }; } //一個實例化后的鏈表,里面是添加的數(shù)個Node類的實例
ES6版本:
let LinkedList2 = (function () { class Node { constructor(element){ this.element = element; this.next = null; } } //這里我們使用WeakMap對象來記錄長度狀態(tài) const length = new WeakMap(); const head = new WeakMap(); class LinkedList2 { constructor () { length.set(this, 0); head.set(this, null); } append(element) { let node = new Node(element), current; if (this.getHead() === null) { head.set(this, node); } else { current = this.getHead(); while (current.next) { current = current.next; } current.next = node; } let l = this.size(); l++; length.set(this, l); } insert(position, element) { if (position >= 0 && position <= this.size()) { let node = new Node(element), current = this.getHead(), previous, index = 0; if (position === 0) { node.next = current; head.set(this, node); } else { while (index++ < position) { previous = current; current = current.next; } node.next = current; previous.next = node; } let l = this.size(); l++; length.set(this, l); return true; } else { return false; } } removeAt(position) { if (position > -1 && position < this.size()) { let current = this.getHead(), previous, index = 0; if (position === 0) { head.set(this, current.next); } else { while (index++ < position) { previous = current; current = current.next; } previous.next = current.next; } let l = this.size(); l--; length.set(this, l); return current.element; } else { return null; } } remove(element) { let index = this.indexOf(element); return this.removeAt(index); } indexOf(element) { let current = this.getHead(), index = 0; while (current) { if (element === current.element) { return index; } index++; current = current.next; } return -1; } isEmpty() { return this.size() === 0; } size() { return length.get(this); } getHead() { return head.get(this); } toString() { let current = this.getHead(), string = ""; while (current) { string += current.element + (current.next ? ", " : ""); current = current.next; } return string; } print() { console.log(this.toString()); } } return LinkedList2; })();雙向鏈表
function DoublyLinkedList() { let Node = function(element){ this.element = element; this.next = null; this.prev = null; //NEW }; let length = 0; let head = null; let tail = null; //NEW this.append = function(element){ let node = new Node(element), current; if (head === null){ head = node; tail = node; //NEW } else { //NEW tail.next = node; node.prev = tail; tail = node; } length++; }; this.insert = function(position, element){ if (position >= 0 && position <= length){ let node = new Node(element), current = head, previous, index = 0; if (position === 0){ if (!head){ //NEW head = node; tail = node; } else { node.next = current; current.prev = node; //NEW head = node; } } else if (position === length) { ////NEW current = tail; current.next = node; node.prev = current; tail = node; } else { while (index++ < position){ previous = current; current = current.next; } node.next = current; previous.next = node; current.prev = node; //NEW node.prev = previous; //NEW } length++; return true; } else { return false; } }; this.removeAt = function(position){ if (position > -1 && position < length){ let current = head, previous, index = 0; if (position === 0){ //NEW if (length === 1){ // tail = null; } else { head.prev = null; } } else if (position === length-1){ //NEW current = tail; tail = current.prev; tail.next = null; } else { while (index++ < position){ previous = current; current = current.next; } previous.next = current.next; current.next.prev = previous; //NEW } length--; return current.element; } else { return null; } }; this.remove = function(element){ let index = this.indexOf(element); return this.removeAt(index); }; this.indexOf = function(element){ let current = head, index = -1; if (element == current.element){ return 0; } index++; while(current.next){ if (element == current.element){ return index; } current = current.next; index++; } //check last item if (element == current.element){ return index; } return -1; }; this.isEmpty = function() { return length === 0; }; this. size = function() { return length; }; this.toString = function(){ let current = head, s = current ? current.element : ""; while(current && current.next){ current = current.next; s += ", " + current.element; } return s; }; this.inverseToString = function() { let current = tail, s = current ? current.element : ""; while(current && current.prev){ current = current.prev; s += ", " + current.element; } return s; }; this.print = function(){ console.log(this.toString()); }; this.printInverse = function(){ console.log(this.inverseToString()); }; this.getHead = function(){ return head; }; this.getTail = function(){ return tail; } }
????雙向鏈表和單項比起來就是Node類多了一個prev屬性,也就是每一個node不僅僅有一個指向它后面元素的指針也有一個指向它前面的指針。
循環(huán)鏈表????明白了前面的基礎(chǔ)鏈表和雙向鏈表之后這個肯定不在話下了,循環(huán),其實就是整個鏈表實例變成了一個圈,在單項鏈表中最后一個元素的next屬性為null,現(xiàn)在讓它指向第一個元素也就是head,那么他就成了單向循環(huán)鏈表。在雙向鏈表中最后一個元素的next屬性為null,現(xiàn)在讓它指向第一個元素也就是head,那么他就成了雙向循環(huán)鏈表。就那么回事...
后記說到現(xiàn)在一直都是線性表,就是順序數(shù)據(jù)結(jié)構(gòu),他們都是有順序的,數(shù)據(jù)都是一條繩子上的螞蚱。那么,如果數(shù)據(jù)是沒有順序的呢?那又該使用哪種數(shù)據(jù)結(jié)構(gòu)呢?這個放到[學(xué)習(xí)javascript數(shù)據(jù)結(jié)構(gòu)(三)——集合]中學(xué)習(xí)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/80886.html
摘要:實現(xiàn)移除給定的元素要移除的元素返回值表示移除成功方法說明移除單向鏈表中某個位置的元素。的前端樂園原文鏈接寒假前端學(xué)習(xí)學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法二鏈表 本系列的第一篇文章: 學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(一),棧與隊列第二篇文章:學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(二):鏈表第三篇文章:學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法(三):集合第四篇文章:學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與...
摘要:在上一篇文章中,我們了解了隊列和棧的描述,現(xiàn)在讓我們來了解一下單鏈表和雙向鏈表的實現(xiàn)。單鏈表和雙向鏈表具有以下特點可動態(tài)分配空間,但不能隨機訪問。 在上一篇文章中,我們了解了隊列和棧的JavaScript描述,現(xiàn)在讓我們來了解一下 單鏈表 和雙向鏈表 的實現(xiàn)。本文的代碼并非所有都由本人所寫,只是出于學(xué)習(xí)目的,在此分享出來,并加上一定的解釋,便于大家學(xué)習(xí)。 本系列文章的代碼可在ht...
摘要:原文博客地址學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)四樹知乎專欄簡書專題前端進(jìn)擊者知乎前端進(jìn)擊者簡書博主博客地址的個人博客人之所能,不能兼?zhèn)?,棄其所短,取其所長。通常子樹被稱作左子樹和右子樹。敬請期待數(shù)據(jù)結(jié)構(gòu)篇最后一篇文章學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)五圖參考文章樹數(shù)據(jù)結(jié)構(gòu)二叉樹 前言 總括: 本文講解了數(shù)據(jù)結(jié)構(gòu)中的[樹]的概念,盡可能通俗易懂的解釋樹這種數(shù)據(jù)結(jié)構(gòu)的概念,使用javascript實現(xiàn)了樹,如有紕漏,歡迎批評指正。 ...
閱讀 3019·2021-09-22 15:54
閱讀 1943·2019-08-30 15:53
閱讀 2331·2019-08-29 16:33
閱讀 1473·2019-08-29 12:29
閱讀 1440·2019-08-26 11:41
閱讀 2431·2019-08-26 11:34
閱讀 3038·2019-08-23 16:12
閱讀 1478·2019-08-23 15:56