JS數(shù)據(jù)結(jié)構(gòu)與算法-二叉樹和二叉查找樹

樹是一種非線性的數(shù)據(jù)結(jié)構(gòu),以分層的方式存儲(chǔ)數(shù)據(jù)。樹被用來(lái)存儲(chǔ)具有層級(jí)關(guān)系的結(jié)構(gòu)芦圾,比如文件系統(tǒng)中的文件;樹還被用來(lái)存儲(chǔ)有序列表俄认。

  1. 二叉樹與二叉查找樹
    二叉樹是一種特殊的樹个少,它的子節(jié)點(diǎn)個(gè)數(shù)不超過(guò)兩個(gè);一個(gè)父節(jié)點(diǎn)的兩個(gè)子節(jié)點(diǎn)分別稱為左節(jié)點(diǎn)和右節(jié)點(diǎn)眯杏。
    二叉查找樹(BST)是一種特殊的二叉樹夜焦;相對(duì)較小的值保持在左節(jié)點(diǎn)中,較大的值保存在右節(jié)點(diǎn)中役拴。

  2. js代碼實(shí)現(xiàn)二叉查找樹

  • 首先我們先定義一個(gè)Node對(duì)象糊探,用于保存數(shù)據(jù)(data),也保存和其他節(jié)點(diǎn)的鏈接(left和right)河闰。
function Node(data,left,right) {
  this.data = data;
  this.left = left;
  this.right = right;
  this.show = show;
}
  • 定義show方法
function show() {
  return this.data;
}
  • 創(chuàng)建一個(gè)類,用來(lái)表示二叉查找樹(BST)
function BST() {
  //將根節(jié)點(diǎn)初始化為null
  this.root = null;
  //insert方法用來(lái)向樹中加入新節(jié)點(diǎn)
  this.insert = insert;
  //inOrder方法用來(lái)遍歷樹
  this.inOrder = inOrder;
}
  • 定義insert方法
function insert(data) {
  //首先實(shí)例化一個(gè)新的Node對(duì)象
  var n = new Node(data,null,null);
  //檢查BST是否有根節(jié)點(diǎn)褥紫,如果沒(méi)有姜性,那么是顆新樹,傳入的該節(jié)點(diǎn)就是根節(jié)點(diǎn)
  if(this.root == null) {
    this.root = n;
  }else {
    //反之就定義一個(gè)current變量用于保存當(dāng)前節(jié)點(diǎn)(根節(jié)點(diǎn))
    var current = this.root;
    var parent;
    while(true) {
      parent = current;
      //如果插入的節(jié)點(diǎn)保存的數(shù)據(jù)小于當(dāng)前節(jié)點(diǎn)髓考,且當(dāng)前節(jié)點(diǎn)的左節(jié)點(diǎn)為null部念,就將這個(gè)新的節(jié)點(diǎn)插入到這個(gè)位置
      if(data < current.data) {
        current = current.left;
        if(current == null) {
          parent.left = n;
          break;
        }
      }else {
        //反之,同理
        current = current.right;
        if(current == null) {
          parent.right = n;
          break;
        }
      }
    }
  }
}
  1. 遍歷二叉查找樹
    有三種遍歷BST的方式
    中序:中序遍歷按照節(jié)點(diǎn)上的鍵值氨菇,以升序訪問(wèn)BST上的所有節(jié)點(diǎn)儡炼。
    先序:先序遍歷先訪問(wèn)根節(jié)點(diǎn),然后以同樣的方式訪問(wèn)左子樹和右子樹查蓉。
    后序:后序遍歷先訪問(wèn)葉子節(jié)點(diǎn)(沒(méi)有任何子節(jié)點(diǎn)的節(jié)點(diǎn))乌询,從左子樹到右子樹,再到根節(jié)點(diǎn)豌研。
    這三種遍歷理解了一種的實(shí)現(xiàn)代碼妹田,其他的都好理解,所以我著重寫一下我對(duì)js代碼實(shí)現(xiàn)中序遍歷過(guò)程的具體理解鹃共。
  • js代碼實(shí)現(xiàn)中序遍歷
    中序遍歷使用遞歸的方式鬼佣,以升序訪問(wèn)樹中所有節(jié)點(diǎn),先訪問(wèn)左子樹霜浴,在訪問(wèn)根節(jié)點(diǎn)晶衷,最后訪問(wèn)右子樹。
function inOrder(node) {
  if(!(node == null)) {
    inOrder(node.left);
    console.log(node.show());
    inOrder(node.right);      
  }
}
//比如:
var nums = new BST();
nums.insert(56);
nums.insert(22);
nums.insert(81);
nums.insert(10);
nums.insert(30);
nums.insert(77);
nums.insert(92);

inOrder(nums.root); //10 22 30 56 81 77 92

①先遞歸遍歷左子樹到盡頭,將每一項(xiàng)push到一個(gè)數(shù)組中晌纫,先是得到這樣的一個(gè)結(jié)果[56,22,10]税迷。

②遞歸完成了,現(xiàn)在pop出第一項(xiàng)即10開始遍歷右子樹,為undefined缸匪。

③然后pop出第二項(xiàng)即22翁狐,遍歷右子樹,得30凌蔬,因?yàn)閏onsole是在先遞歸左子樹后打印的露懒,所以把30插到(push)56和22中間,結(jié)果為[56,30,22,10]砂心。

④然后pop出第三項(xiàng)即30懈词,undefined。

⑤然后pop出第四項(xiàng)即56辩诞,遍歷該右子樹坎弯,得結(jié)果[92,81,56,30,22,10]

⑥然后pop出第五項(xiàng)即81,發(fā)現(xiàn)有左子樹77译暂,所以push進(jìn)去抠忘,又因?yàn)閏onsole代碼在中間,所以要放到92和81中間外永,結(jié)果[92,81,77,56,30,22,10]所以最后打印結(jié)果為10,22,30,56,77,81,92

理解了一個(gè)崎脉,后面的先序遍歷和后序遍歷就沒(méi)問(wèn)題了,只是console代碼放置的位置不同伯顶。主要是理解遞歸囚灼。

  • 先序遍歷
function inOrder(node) {
  if(!(node == null)) {
    console.log(node.show());
    inOrder(node.left);
    inOrder(node.right);      
  }
}
inOrder(nums.root);
  • 后序遍歷
function inOrder(node) {
  if(!(node == null)) {
    inOrder(node.left);
    inOrder(node.right);      
    console.log(node.show());
  }
}
inOrder(nums.root);

參考學(xué)習(xí)

《數(shù)據(jù)結(jié)構(gòu)與算法JavaScript描述》
《高程》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市祭衩,隨后出現(xiàn)的幾起案子灶体,更是在濱河造成了極大的恐慌,老刑警劉巖掐暮,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝎抽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡劫乱,警方通過(guò)查閱死者的電腦和手機(jī)织中,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)衷戈,“玉大人狭吼,你說(shuō)我怎么就攤上這事≈掣荆” “怎么了刁笙?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我疲吸,道長(zhǎng)座每,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任摘悴,我火速辦了婚禮峭梳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蹂喻。我一直安慰自己葱椭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布口四。 她就那樣靜靜地躺著孵运,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蔓彩。 梳的紋絲不亂的頭發(fā)上治笨,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音赤嚼,去河邊找鬼旷赖。 笑死,一個(gè)胖子當(dāng)著我的面吹牛更卒,可吹牛的內(nèi)容都是我干的杠愧。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼逞壁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了锐锣?” 一聲冷哼從身側(cè)響起腌闯,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎雕憔,沒(méi)想到半個(gè)月后姿骏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡斤彼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年分瘦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琉苇。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嘲玫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出并扇,到底是詐尸還是另有隱情去团,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站土陪,受9級(jí)特大地震影響昼汗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鬼雀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一顷窒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧源哩,春花似錦鞋吉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至崩侠,卻和暖如春漆魔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背却音。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工改抡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人系瓢。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓阿纤,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親夷陋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子欠拾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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