成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

「算法與數據結構」二叉樹之美

開發 前端 算法
這次梳理的內容是數據結構專題中的「樹」,如果你看到樹這類數據結構時,滿腦子頭疼,覺得它很難理解,如果是這樣子的話,那么本文可能對你或許有點幫助。

[[349809]]

 前言

這次梳理的內容是數據結構專題中的「樹」,如果你看到樹這類數據結構時,滿腦子頭疼,覺得它很難理解,如果是這樣子的話,那么本文可能對你或許有點幫助。

俗話說得好,要想掌握理解的話,我們得先了解它的概念,性質等內容。

圍繞以下幾個點來展開介紹樹👇

樹的基本概念

  • 基本術語
  • 樹的種類
  • 二叉樹概念
  • 二叉樹的遍歷
  • 二叉樹題目匯總

腦圖👇

 

 

 

 

樹的基本概念

樹是用來模擬具有樹狀結構性質的數據集合。或者你可以把它認為是一種「抽象數據結構」或是實現這種抽象數據類型的數據結構,用來模擬具有樹狀結構性質的數據集合。

那么根據維基百科給出的定義,我們似乎可以這么理解:

它是由n(n>0)個有限節點組成一個具有層次關系的集合。把它叫做“樹”是因為它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。它具有以下的特點:

  • 每個節點都只有有限個子節點或無子節點;
  • 沒有父節點的節點稱為根節點;
  • 每一個非根節點有且只有一個父節點;
  • 除了根節點外,每個子節點可以分為多個不相交的子樹;
  • 樹里面沒有環路(cycle)

這個時候,我們就需要拿出一張圖來看👇

 

 

 

 

從圖中來看,以上的五個特點都可以很好的總結出來

  • A節點作為根節點,沒有父節點,所以是根節點。
  • 除根節點(A)外,其他的節點都有父節點,并且每個節點只有有限個子節點或無子節點。
  • 從某個節點開始,可以分為很多個子樹,舉個例子,從B節點開始,即是如此。

既然對樹有一定認識后,我們需要了解它的一些術語。

基本術語

 


樹的基本術語

 

 

為了更加規范的總結,這里給出的描述來自于維基百科:

  • 「節點的度」:一個節點含有的子樹的個數稱為該節點的度;
  • 「樹的度」:一棵樹中,最大的節點度稱為樹的度;
  • 「葉節點」或「終端節點」:度為零的節點;
  • 「非終端節點」或「分支節點」:度不為零的節點;
  • 「父親節點」或「父節點」:若一個節點含有子節點,則這個節點稱為其子節點的父節點;
  • 「孩子節點」或「子節點」:一個節點含有的子樹的根節點稱為該節點的子節點;
  • 「兄弟節點」:具有相同父節點的節點互稱為兄弟節點;
  • 節點的「層次」:從根開始定義起,根為第1層,根的子節點為第2層,以此類推;
  • 「深度」:對于任意節點n,n的深度為從根到n的唯一路徑長,根的深度為0;
  • 「高度」:對于任意節點n,n的高度為從n到一片樹葉的最長路徑長,所有樹葉的高度為0;
  • 「堂兄弟節點」:父節點在同一層的節點互為堂兄弟;
  • 「節點的祖先」:從根到該節點所經分支上的所有節點;
  • 「子孫」:以某節點為根的子樹中任一節點都稱為該節點的子孫;
  • 「森林」:由m(m>=0)棵互不相交的樹的集合稱為森林。

可以結合上述的圖來理解這些概念,通過兩者的結合,你一定會對樹有進一步的了解的。

有以上基本概念,以及一些專業術語的掌握,接下來我們需要對樹進行一個分類,看看樹有哪些種類。

樹的種類

理解了樹的概念以及基本術語,接下來,我們需要拓展的內容就是樹的種類。

我們可以根據維基百科的依據來作為分類的標準👇

  • 無序樹:樹中任意節點的子節點之間沒有順序關系,這種樹稱為無序樹,也稱為自由樹;
  • 有序樹:樹中任意節點的子節點之間有順序關系,這種樹稱為有序樹;
  • 完全二叉樹:對于一顆二叉樹,假設其深度為d(d>1)。除了第d層外,其它各層的節點數目均已達最大值,且第d層所有節點從左向右連續地緊密排列,這樣的二叉樹被稱為完全二叉樹;
  • 平衡二叉樹(AVL樹):當且僅當任何節點的兩棵子樹的高度差不大于1的二叉樹;
  • 排序二叉樹(英語:Binary Search Tree)):也稱二叉搜索樹、有序二叉樹;
  • 滿二叉樹:所有葉節點都在最底層的完全二叉樹;
  • 二叉樹:每個節點最多含有兩個子樹的樹稱為二叉樹;
  • 霍夫曼樹:帶權路徑最短的二叉樹稱為哈夫曼樹或最優二叉樹;
  • B樹:一種對讀寫操作進行優化的自平衡的二叉查找樹,能夠保持數據有序,擁有多于兩個子樹。

既然樹的分類有這么多的話,那么我們是不是都需要一一掌握呢,我個人覺得,掌握二叉樹這種結構就足夠了,它也是樹最簡單、應用最廣泛的種類。

那么接下來,我們就來介紹一下二叉樹吧。

二叉樹的概念

二叉樹是一種典型的樹樹狀結構。如它名字所描述的那樣,二叉樹是每個節點最多有兩個子樹的樹結構,通常子樹被稱作“左子樹”和“右子樹”。

 

 


二叉樹

 

 

從這個圖片的內容來看,應該很清楚的展示了二叉樹的結構。

至于二叉樹的性質的話,可以參考下圖,作為補充知識吧,個人覺得這個不是重點。

 

 


二叉樹的性質

 

 

重點的話,我們需要掌握的應該是它的遍歷方式。

二叉樹的遍歷

我們知道對于二叉樹的遍歷而言,有常見得三種遍歷方式,分別是以下三種:

  • 前序遍歷
  • 中序遍歷
  • 后續遍歷

對于任何一種遍歷方式而言,我們不僅需要掌握它的非遞歸版本,同時對于它的遞歸版本來說,更是考察一個人的算法基本功,那么接下來,我們來看看吧。

前序遍歷

點擊這里,練習二叉樹的前序遍歷

給你二叉樹的根節點 root ,返回它節點值的 「前序」 遍歷。

假設我們mock一下假數據👇

  1. 輸入: [1,null,2,3] 
  2.    1 
  3.     \ 
  4.      2 
  5.     / 
  6.    3 
  7. 輸出: [1,3,2] 

那么根據我們對前序遍歷的理解,我們可以寫出解題偽代碼👇

  1. //   TianTianUp 
  2. //   * function TreeNode(val, leftright) { 
  3. //   *     this.val = (val===undefined ? 0 : val) 
  4. //   *     this.left = (left===undefined ? null : left
  5. //   *     this.right = (right===undefined ? null : right
  6. //   * } 
  7. let inorderTraversal  = (root, arr = []) => { 
  8.   if(root) { 
  9.     inorderTraversal(root.left, arr) 
  10.     arr.push(root.value) 
  11.     inorderTraversal(root.right, arr) 
  12.   } 
  13.   return arr 

非遞歸版本👇

對于非遞歸的話,我們需要借助一個數據結構去存儲它的節點,需要使用的就是棧,它的思路可以借鑒👇

  • 根節點為目標節點,開始向它子節點遍歷
  • 1.訪問目標節點
  • 2.左孩子入棧 -> 直至左孩子為空的節點
  • 3.節點出棧,以右孩子為目標節點,再依次執行1、2、3
  1. let preorderTraversal = (root, arr = []) => { 
  2.   const stack = [], res = [] 
  3.   let current = root 
  4.   while(current || stack.length > 0) { 
  5.     while (current) { 
  6.       res.push(current.val) 
  7.       stack.push(current
  8.       current = current.left 
  9.     } 
  10.     current = stack.pop() 
  11.     current = current.right 
  12.   } 
  13.   return res 

中序遍歷

給定一個二叉樹,返回它的中序 遍歷。

示例:

  • 輸入: [1,null,2,3] 1
  • 2 / 3
  • 輸出: [1,3,2]

進階: 遞歸算法很簡單,你可以通過迭代算法完成嗎?

遞歸版本👇

  1. const inorderTraversal  = (root, arr = []) => { 
  2.   if(root) { 
  3.     inorderTraversal(root.left, arr) 
  4.     arr.push(root.val) 
  5.     inorderTraversal(root.right, arr) 
  6.   } 
  7.   return arr 

非遞歸版本,這里就不解釋了,跟前序遍歷一樣,思路一樣,用棧維護節點信息。

  1. const inorderTraversal = (root, arr = []) => { 
  2.   const stack = [], res = [] 
  3.   let current = root 
  4.   while(current || stack.length > 0) { 
  5.     while (current) { 
  6.       stack.push(current
  7.       current = current.left 
  8.     } 
  9.     current = stack.pop() 
  10.     res.push(current.val) 
  11.     current = current.right 
  12.   } 
  13.   return res 

后續遍歷

給定一個二叉樹,返回它的 后序 遍歷。

示例:

  • 輸入: [1,null,2,3]
  • 1
  • 2 / 3
  • 輸出: [3,2,1]

進階: 遞歸算法很簡單,你可以通過迭代算法完成嗎?

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal 著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。

遞歸版本👇

  1. const postorderTraversal  = (root, arr = []) => { 
  2.   if(root) { 
  3.     postorderTraversal(root.left, arr) 
  4.     postorderTraversal(root.right, arr) 
  5.     arr.push(root.val) 
  6.   } 
  7.   return arr 

非遞歸版本👇

其實,嗯,做完前面兩個后,會發現都是有套路滴~

  1. const postorderTraversal = (root, arr = []) => { 
  2.   const stack = [], res = [] 
  3.   let current = root, last = null  // last指針記錄上一個節點 
  4.   while(current || stack.length > 0) { 
  5.     while (current) { 
  6.       stack.push(current
  7.       current = current.left 
  8.     } 
  9.     current = stack[stack.length - 1] 
  10.     if (!current.right || current.right == last) { 
  11.       current = stack.pop() 
  12.       res.push(current.val) 
  13.       last = current 
  14.       current = null              // 繼續彈棧 
  15.     } else { 
  16.       current = current.right 
  17.     } 
  18.   } 
  19.   return res 

二叉樹的層次遍歷 ⭐⭐

鏈接:二叉樹的層序遍歷

給你一個二叉樹,請你返回其按 「層序遍歷」 得到的節點值。(即逐層地,從左到右訪問所有節點)。

示例:二叉樹:[3,9,20,null,null,15,7],

  • 3
  • /
  • 9 20 /
  • 15 7

返回其層次遍歷結果:

  • [ [3], [9,20], [15,7] ]

來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal 著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。

遞歸版本👇

  1. const levelOrder = function(root) { 
  2.   if(!root) return [] 
  3.   let res = [] 
  4.   dfs(root, 0, res) 
  5.   return res 
  6.  
  7. function dfs(root, step, res){ 
  8.   if(root){ 
  9.       if(!res[step]) res[step] = [] 
  10.       res[step].push(root.val) 
  11.       dfs(root.left, step + 1, res) 
  12.       dfs(root.right, step + 1, res) 
  13.     } 

非遞歸版本👇

這里借助的就是隊列這個數據結構,先進先出的機制。

  1. const levelOrder = (root) => { 
  2.   let queue = [], res = [] 
  3.   if (root) queue.push(root); 
  4.   while (queue.length) { 
  5.       let next_queue = [], 
  6.           now_res = [] 
  7.       while (queue.length) { 
  8.           root = queue.shift() 
  9.           now_res.push(root.val) 
  10.           root.left && next_queue.push(root.left
  11.           root.right && next_queue.push(root.right
  12.       } 
  13.       queue = next_queue 
  14.       res.push(now_res) 
  15.   } 
  16.   return res 

題目匯總

還是那句話,題目做不完的,剩下的就靠刷leetcode了,我還準備了一些常見的二叉樹題集,題目的質量還是不錯的👇

  • 二叉樹的最小深度⭐
  • 二叉樹的最大深度⭐
  • 相同的樹⭐
  • 二叉搜索樹的范圍和⭐
  • 對稱二叉樹⭐
  • 將有序數組轉換為二叉搜索樹⭐
  • 二叉樹的層次遍歷 II⭐⭐
  • 二叉樹的最近公共祖先⭐⭐
  • 驗證二叉搜索樹⭐⭐
  • 路徑總和 III⭐⭐
  • 存在重復元素 III⭐⭐
  • 計算右側小于當前元素的個數⭐⭐⭐

 

 

責任編輯:姜華 來源: 前端UpUp
相關推薦

2020-09-23 18:25:40

算法二叉樹多叉樹

2021-04-28 20:12:27

數據結構創建

2021-04-01 10:34:18

Java編程數據結構算法

2021-03-19 10:25:12

Java數據結構算法

2021-04-20 08:37:14

數據結構二叉樹

2021-04-19 07:47:42

數據結構二叉樹Tree

2021-03-22 09:00:22

Java數據結構算法

2013-01-30 10:34:02

數據結構

2020-10-30 09:56:59

Trie樹之美

2023-04-06 07:39:48

2021-01-07 08:12:47

數據結構二叉樹

2021-03-29 10:13:47

Java編程數據結構算法

2013-07-15 16:35:55

二叉樹迭代器

2021-09-29 10:19:00

算法平衡二叉樹

2020-04-27 07:05:58

二叉樹左子樹右子樹

2021-03-22 08:23:29

LeetCode二叉樹節點

2018-03-15 08:31:57

二叉樹存儲結構

2021-09-15 07:56:32

二叉樹層次遍歷

2021-10-12 09:25:11

二叉樹樹形結構

2019-08-22 09:22:44

數據結構二叉搜索樹
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 韩国精品在线 | 久久精品色欧美aⅴ一区二区 | 区一区二在线观看 | 91在线中文字幕 | 男女羞羞视频在线 | 精品国产第一区二区三区 | 国产精品一区二区三区四区 | 在线一区 | 国产成人免费网站 | 综合色播| 久久免费视频观看 | www.一级毛片 | 中文二区 | 久久一区二区免费视频 | 欧美日韩亚洲二区 | 精品国产乱码久久久久久老虎 | 久久久久久国产精品免费免费 | 91九色在线观看 | 国产精品片 | 国产在线精品一区二区三区 | 最近日韩中文字幕 | 午夜精品久久久久久久久久久久久 | 日韩欧美三区 | 色播久久久 | 成人一区二区三区在线观看 | 男人天堂久久 | 三a毛片 | 午夜久草 | 91久久久久久久久久久久久 | 永久精品 | 精品日韩一区 | 精品一区二区三区电影 | 久久综合狠狠综合久久 | 国产一区二区免费 | 午夜精品一区二区三区三上悠亚 | 久久久久国产 | 久久夜色精品国产 | 国产精品jizz在线观看老狼 | 亚洲在线中文字幕 | 成人综合视频在线观看 | 久久99精品久久久久久 |