最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript數(shù)據(jù)結(jié)構(gòu)之鏈表的實現(xiàn)

 更新時間:2017年03月19日 11:59:13   作者:君君wan歲  
鏈表是一種常見的數(shù)據(jù)結(jié)構(gòu)。它是動態(tài)地進(jìn)行存儲分配的一種結(jié)構(gòu)。本文主要介紹JavaScript數(shù)據(jù)結(jié)構(gòu)中鏈表的實現(xiàn),具有很好的參考價值。下面跟著小編一起來看下吧

前面樓主分別討論了數(shù)據(jù)結(jié)構(gòu)棧與隊列的實現(xiàn),當(dāng)時所用的數(shù)據(jù)結(jié)構(gòu)都是用的數(shù)組來進(jìn)行實現(xiàn),但是數(shù)組有的時候并不是最佳的數(shù)據(jù)結(jié)構(gòu),比如在數(shù)組中新增刪除元素的時候需要將其他元素進(jìn)行移動,而在javascript中使用spit()方法不需要訪問其他元素。如果你在使用數(shù)組的時候發(fā)現(xiàn)很慢,就可以考慮使用鏈表。

鏈表的概念

鏈表是一種常見的數(shù)據(jù)結(jié)構(gòu)。它是動態(tài)地進(jìn)行存儲分配的一種結(jié)構(gòu)。鏈表有一個“頭指針”變量,以head表示,它存放一個地址,指向一個元素。每個結(jié)點都使用一個對象的引用指標(biāo)它的后繼,指向另一個結(jié)點的引用叫做鏈。

數(shù)組元素依靠下標(biāo)(位置)來進(jìn)行引用,而鏈表元素則是靠相互之間的關(guān)系來進(jìn)行引用。因此鏈表的插入效率很高,下圖演示了鏈表結(jié)點d的插入過程: 

 

刪除過程:

基于對象的鏈表

我們定義2個類,Node類與LinkedList類,Node為結(jié)點數(shù)據(jù),LinkedList保存操作鏈表的方法。

首先看Node類:  

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

element用來保存結(jié)點上的數(shù)據(jù),next用來保存指向一下結(jié)點的的鏈接。  

LinkedList類:

function LinkedList(){
     this.head = new Node('head');
     this.find = find;
     this.insert = insert;
     this.remove = remove;
     this.show = show;
}

find()方法,從頭結(jié)點開始,沿著鏈表結(jié)點一直查找,直到找到與item內(nèi)容相等的element則返回該結(jié)點,沒找到則返回空。

function find(item){
     var currentNode = this.head;//從頭結(jié)點開始
     while(currentNode.element!=item){
         currentNode = currentNode.next;
     }
     return currentNode;//找到返回結(jié)點數(shù)據(jù),沒找到返回null
}

Insert方法。通過前面元素插入的演示可以看出,實現(xiàn)插入簡單四步:

1、創(chuàng)建結(jié)點

2、找到目標(biāo)結(jié)點

3、修改目標(biāo)結(jié)點的next指向鏈接

4、將目標(biāo)結(jié)點的next值賦值給要插入的結(jié)點的next

function insert(newElement,item){
     var newNode = new Node(newElement);
     var currentNode = this.find(item);
     newNode.next = currentNode.next;
     currentNode.next = newNode;
 }

Remove()方法。刪除某一節(jié)點需要先找到被刪除結(jié)點的前結(jié)點,為此我們定義方法frontNode():

function frontNode(item){
     var currentNode = this.head;
     while(currentNode.next.element!=item&&currentNode.next!=null){
         currentNode = currentNode.next;
     }   
     return currentNode;
}

簡答三步:

1、創(chuàng)建結(jié)點

2、找到目標(biāo)結(jié)點的前結(jié)點

3、修改前結(jié)點的next指向被刪除結(jié)點的n后一個結(jié)點

function remove(item){
     var frontNode = this.frontNode(item);
     //console.log(frontNode.element);
     frontNode.next = frontNode.next.next;
 }

Show()方法:

function show(){
     var currentNode = this.head,result;
     while(currentNode.next!=null){
         result += currentNode.next.element;//為了不顯示head結(jié)點
         currentNode = currentNode.next;
     }
}

測試程序:

var list = new LinkedList();
list.insert("a","head");
list.insert("b","a");
list.insert("c","b");
console.log(list.show());
list.remove("b");
console.log(list.show());

輸出:

雙向鏈表

從鏈表的頭節(jié)點遍歷到尾節(jié)點很簡單,但有的時候,我們需要從后向前遍。此時我們可以通過給 Node 對象增加一個屬性,該屬性存儲指向前驅(qū)節(jié)點的鏈接。樓主用下圖來雙向鏈表的工作原理。

首先我們先給Node類增加front屬性:  

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

當(dāng)然,對應(yīng)的insert()方法和remove()方法我們也需要做相應(yīng)的修改: 

function insert(newElement,item){
  var newNode = new Node(newElement);
  var currentNode = this.find(item);
  newNode.next = currentNode.next;
  newNode.front = currentNode;//增加front指向前驅(qū)結(jié)點
  currentNode.next = newNode;
}
function remove(item){  
  var currentNode = this.find(item);//找到需要刪除的節(jié)點
  if (currentNode.next != null) {
    currentNode.front.next = currentNode.next;//讓前驅(qū)節(jié)點指向需要刪除的節(jié)點的下一個節(jié)點
    currentNode.next.front = currentNode.front;//讓后繼節(jié)點指向需要刪除的節(jié)點的上一個節(jié)點
    currentNode.next = null;//并設(shè)置前驅(qū)與后繼的指向為空
    currentNode.front = null;    
  }  
}

反序顯示鏈表:

需要給雙向鏈表增加一個方法,用來查找最后的節(jié)點。 findLast() 方法找出了鏈表中的最后一個節(jié)點,可以免除從前往后遍歷鏈。

function findLast() {//查找鏈表的最后一個節(jié)點
  var currentNode = this.head;
  while (currentNode.next != null) {
    currentNode = currentNode.next;
  }
  return currentNode;
}

實現(xiàn)反序輸出:

function showReverse() {
  var currentNode = this.head, result = "";
  currentNode = this.findLast(); 
  while(currentNode.front!=null){
    result += currentNode.element + " ";
    currentNode = currentNode.front;
  }
  return result;
}

測試程序:

var list = new LinkedList();
list.insert("a","head");
list.insert("b","a");
list.insert("c","b");
console.log(list);
list.remove("b");
console.log(list.show());
console.log(list.showReverse());

輸出:

循環(huán)鏈表

循環(huán)鏈表是另一種形式的鏈?zhǔn)酱尜A結(jié)構(gòu)。它的特點是表中最后一個結(jié)點的指針域指向頭結(jié)點,整個鏈表形成一個環(huán)。循環(huán)鏈表和單向鏈表相似,節(jié)點類型都是一樣的。唯一的區(qū)別是,在創(chuàng)建循環(huán)鏈表時,讓其頭節(jié)點的 next 屬性指向它本身,即:

head.next = head

這種行為會傳導(dǎo)至鏈表中的每個節(jié)點,使得每個節(jié)點的 next 屬性都指向鏈表的頭節(jié)點。樓主用下圖來表示循環(huán)鏈表:

修改構(gòu)造方法:

function LinkedList(){
  this.head = new Node('head');//初始化
  this.head.next = this.head;//直接將頭節(jié)點的next指向頭節(jié)點形成循環(huán)鏈表
  this.find = find;
  this.frontNode = frontNode;
  this.insert = insert;
  this.remove = remove;
  this.show = show; 
}

這時需要注意鏈表的輸出方法show()與find()方法,原來的方式在循環(huán)鏈表里會陷入死循環(huán),while循環(huán)的循環(huán)條件需要修改為當(dāng)循環(huán)到頭節(jié)點時退出循環(huán)。

function find(item){
  var currentNode = this.head;//從頭結(jié)點開始
  while(currentNode.element!=item&&currentNode.next.element!='head'){
    currentNode = currentNode.next;
  }
  return currentNode;//找到返回結(jié)點數(shù)據(jù),沒找到返回null
}
function show(){
  var currentNode = this.head,result = "";
  while (currentNode.next != null && currentNode.next.element != "head") {   
    result += currentNode.next.element + " ";
    currentNode = currentNode.next;
  }
  return result;
}

測試程序:

var list = new LinkedList();
list.insert("a","head");
list.insert("b","a");
list.insert("c","b");
console.log(list.show());
list.remove("b");
console.log(list.show());

測試結(jié)果:

本文用到的示例代碼地址:https://github.com/LJunChina/JavaScript

以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!

相關(guān)文章

  • 事件綁定之小測試  onclick && addEventListener

    事件綁定之小測試 onclick && addEventListener

    昨晚回去后,和雷子討論如何才能“檢測”到頁面上某個元素都綁定了哪些事件監(jiān)聽函數(shù),第一感覺就是應(yīng)該從瀏覽器入手,比如FF,或者Chrome等
    2011-07-07
  • 去除element-ui中Dialog對話框遮罩層方法詳解

    去除element-ui中Dialog對話框遮罩層方法詳解

    這篇文章主要為大家介紹了去除element-ui中Dialog對話框遮罩層方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 深入理解JS中的微任務(wù)和宏任務(wù)的執(zhí)行順序及應(yīng)用場景

    深入理解JS中的微任務(wù)和宏任務(wù)的執(zhí)行順序及應(yīng)用場景

    JavaScript中的任務(wù)分為宏任務(wù)和微任務(wù),它們的執(zhí)行順序會影響代碼的執(zhí)行結(jié)果。了解它們的機(jī)制可以幫助我們更好地理解事件循環(huán)和異步編程,避免出現(xiàn)一些意想不到的錯誤
    2023-05-05
  • JavaScript圖像延遲加載庫Echo.js

    JavaScript圖像延遲加載庫Echo.js

    Echo 是一個獨立的 JavaScript 懶加載圖像的工具,快速、體積小(不足1k)和使用 HTML5 的 data- 屬性,通過本文給大家介紹JavaScript圖像延遲加載庫Echo.js ,感興趣的朋友一起學(xué)習(xí)吧
    2016-04-04
  • JS+CSS實現(xiàn)Div彈出窗口同時背景變暗的方法

    JS+CSS實現(xiàn)Div彈出窗口同時背景變暗的方法

    這篇文章主要介紹了JS+CSS實現(xiàn)Div彈出窗口同時背景變暗的方法,是一款比較典型的javascript操作彈出窗口的技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-03-03
  • JavaScript實現(xiàn)快速排序的方法分析

    JavaScript實現(xiàn)快速排序的方法分析

    這篇文章主要介紹了JavaScript實現(xiàn)快速排序的方法,結(jié)合實例形式分析了快速排序的原理、實現(xiàn)方法及相關(guān)操作注意事項,需要的朋友可以參考下
    2018-01-01
  • BootStrap 彈出層代碼

    BootStrap 彈出層代碼

    這篇文章主要介紹了BootStrap 彈出層代碼的相關(guān)資料,非常補(bǔ)充,具有參考借鑒價值,需要的朋友可以參考下
    2017-02-02
  • js實現(xiàn)點擊切換checkbox背景圖片的簡單實例

    js實現(xiàn)點擊切換checkbox背景圖片的簡單實例

    下面小編就為大家?guī)硪黄猨s實現(xiàn)點擊切換checkbox背景圖片的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • 深入了解JavaScript詞法作用域

    深入了解JavaScript詞法作用域

    這篇文章主要介紹了JavaScript詞法作用域的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 異步動態(tài)加載JS并運行(示例代碼)

    異步動態(tài)加載JS并運行(示例代碼)

    這篇文章主要是對異步動態(tài)加載JS并運行的示例代碼進(jìn)行了介紹。需要的朋友可以過來參考下,希望對大家有所幫助
    2013-12-12

最新評論

中方县| 班玛县| 永宁县| 栾城县| 元氏县| 香格里拉县| 黑龙江省| 唐山市| 许昌市| 保亭| 荥经县| 略阳县| 泊头市| 松滋市| 衡阳市| 潜山县| 来安县| 井陉县| 丹巴县| 兴国县| 阿拉善盟| 威宁| 桂平市| 喀什市| 阳东县| 土默特右旗| 平罗县| 东城区| 胶南市| 新营市| 长丰县| 万安县| 田阳县| 资阳市| 连州市| 津市市| 定结县| 宕昌县| 新闻| 阳西县| 桂林市|