摘要:簡介二叉樹是一種非常重要的數據結構,很多其它數據結構都是基于二叉樹的基礎演變而來的。二叉搜索樹是二叉樹的一種,但是它只允許你在左側節點存儲比父節點小的值,在右側節點存儲比父節點大或者等于的值。樹的高度,樹的高度體現為節點深度的最大值。
簡介
二叉樹是一種非常重要的數據結構,很多其它數據結構都是基于二叉樹的基礎演變而來的。
對于二叉樹,有深度遍歷和廣度遍歷,深度遍歷有前序、中序以及后序三種遍歷方法,廣度遍歷即我們平常所說的層次遍歷。因為樹的定義本身就是遞歸定義,因此采用遞歸的方法去實現樹的三種遍歷不僅容易理解而且代碼很簡潔,而對于廣度遍歷來說,需要其他數據結構的支撐,比如堆了。
二叉樹中的節點最多只能有兩個節點:一個是左側子節點,另一個是右側子節點。
二叉搜索樹(BST)是二叉樹的一種,但是它只允許你在左側節點存儲(比父節點)小的值,在右側節點存儲(比父節點)大(或者等于)的值。
樹中的每個元素,都叫做節點。從節點延伸而下的,叫子節點。
樹頂部的節點叫根節點。每棵樹只有一個根節點。
在節點中,有子節點的節點也稱為內部節點,沒有的話則被稱為外部節點或者葉節點。
同時在節點中是有祖先和后代關系的,比如節點9的祖先就有13,7,6,15四個。
深度: 節點的深度取決于其祖先的數量,節點9的深度就是4。
樹的高度,樹的高度體現為節點深度的最大值。
比如上圖,節點深度最大值為4,則樹的高度為4。
下面我們先來簡單實現一個二叉搜索樹類,并包含以下的方法:
insert(key): 向樹中插入一個新的鍵
min(): 返回樹中最小的值
max(): 返回樹中最大的值
search(key): 搜索某個值,在樹中則返回true
remove(key): 從樹中移除某個鍵
代碼如下:
function BinarySearchTree() { var Node = function(key){ //數據結構類 this.key = key; this.left = null; this.right = null; }; var root = null; //根節點 this.insert = function(key){ //插入新的鍵 var newNode = new Node(key); //special case - first element if (root === null){ //根節點為空,作為根節點 root = newNode; } else { insertNode(root,newNode); //插入節點操作 } }; var insertNode = function(node, newNode){ if (newNode.key < node.key){ if (node.left === null){ //如果沒有左側節點就插入新的節點 node.left = newNode; } else { //有的話遞歸 insertNode(node.left, newNode); } } else { if (node.right === null){ //如果沒有右側節點就插入新的節點 node.right = newNode; } else { //有的話遞歸 insertNode(node.right, newNode); } } }; this.getRoot = function(){ return root; }; this.search = function(key){ //搜索鍵 return searchNode(root, key); //搜索操作 }; var searchNode = function(node, key){ if (node === null){ return false; } if (key < node.key){ //如果小于繼續從左邊搜索 return searchNode(node.left, key); } else if (key > node.key){ //如果大于繼續從右邊搜索 return searchNode(node.right, key); } else { //命中 return true; } }; this.min = function() { //找最小鍵 return minNode(root); }; var minNode = function (node) { if (node){ while (node && node.left !== null) { node = node.left; } return node.key; } return null; }; this.max = function() { //找最大鍵 return maxNode(root); }; var maxNode = function (node) { if (node){ while (node && node.right !== null) { node = node.right; } return node.key; } return null; }; this.remove = function(element){ root = removeNode(root, element); }; var findMinNode = function(node){ //返回節點 while (node && node.left !== null) { node = node.left; } return node; }; var removeNode = function(node, element){ //移除一個節點 if (node === null){ return null; } if (element < node.key){ node.left = removeNode(node.left, element); return node; } else if (element > node.key){ node.right = removeNode(node.right, element); return node; } else { //命中后分三種情況 //移除葉子節點,即該節點沒有左側或者右側子節點的葉結點 if (node.left === null && node.right === null){ node = null; return node; } //移除有一個左側或者右側子節點的節點 if (node.left === null){ node = node.right; //把引用改為子節點的引用,下同 return node; } else if (node.right === null){ node = node.left; return node; } //移除有兩個子節點的節點 var aux = findMinNode(node.right); //找到右邊子樹的最小節點 node.key = aux.key; //改變節點的鍵,更新節點的值 node.right = removeNode(node.right, aux.key); //移除有相同鍵的節點 return node; //返回更新后節點的引用 } }; }二叉樹的遍歷
前序遍歷:根結點 ---> 左子樹 ---> 右子樹
中序遍歷:左子樹---> 根結點 ---> 右子樹
后序遍歷:左子樹 ---> 右子樹 ---> 根結點
層次遍歷:只需按層次遍歷即可
例如,求下面二叉樹的各種遍歷
前序遍歷:1 2 4 5 7 8 3 6
中序遍歷:4 2 7 5 8 1 3 6
后序遍歷:4 7 8 5 2 6 3 1
層次遍歷:1 2 3 4 5 6 7 8
代碼實現如下:
/** * 先序遍歷 * @param {any} callback 回調函數 */ this.preOrderTranverse = function (callback) { preOrderTranverseNode(root, callback) } var preOrderTranverseNode = function (node, callback) { if (node !== null) { callback && callback(node.key); preOrderTranverseNode(node.left, callback); preOrderTranverseNode(node.right, callback); } }中序遍歷
代碼實現如下:
/**
中序遍歷
@param {any} callback 回調函數
*/
this.inOrderTraverse = function (callback) {
inOrderTraverseNode(root, callback)
}
var inOrderTraverseNode = function (node, callback) {
if (node !== null) { inOrderTraverseNode(node.left, callback); callback && callback(node.key) inOrderTraverseNode(node.right, callback); }
}
后序遍歷代碼實現如下:
/** * 后序遍歷 * @param {any} callback 回調函數 */ this.postOrderTranverse = function (callback) { postOrderTranverseNode(root, callback); } var postOrderTranverseNode = function (node, callback) { if (node !== null) { postOrderTranverseNode(node.left, callback); postOrderTranverseNode(node.right, callback); callback(node.key); } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89292.html
摘要:二叉搜索樹是二叉樹的一種,其特征是左側子節點存儲比父節點小的值,右側子節點存儲比父節點大或等于父節點的值。實現和這個兩個方法其實挺簡單的,最小的節點就在二叉搜索樹的最左反之,最大的就在最右。 本系列所有文章:第一篇文章:學習數據結構與算法之棧與隊列第二篇文章:學習數據結構與算法之鏈表第三篇文章:學習數據結構與算法之集合第四篇文章:學習數據結構與算法之字典和散列表第五篇文章:學習數據結構...
摘要:像剛才的這幅圖,就是二叉搜索樹。而我們本文要學習的內容,就是如何寫一個二叉搜索樹。但在二叉搜索樹中,我們把節點成為鍵,這是術語。前端路漫漫,且行且歌的前端樂園原文鏈接寒假前端學習學習數據結構與算法四二叉搜索樹 本系列的第一篇文章: 學習JavaScript數據結構與算法(一),棧與隊列第二篇文章:學習JavaScript數據結構與算法(二):鏈表第三篇文章:學習JavaScript數據...
摘要:原文博客地址學習數據結構四樹知乎專欄簡書專題前端進擊者知乎前端進擊者簡書博主博客地址的個人博客人之所能,不能兼備,棄其所短,取其所長。通常子樹被稱作左子樹和右子樹。敬請期待數據結構篇最后一篇文章學習數據結構五圖參考文章樹數據結構二叉樹 前言 總括: 本文講解了數據結構中的[樹]的概念,盡可能通俗易懂的解釋樹這種數據結構的概念,使用javascript實現了樹,如有紕漏,歡迎批評指正。 ...
摘要:筆者作為一位,將工作以來用到的各種優秀資料神器及框架整理在此,畢竟好記性不如爛鍵盤,此前端知識點大百科全書前端掘金,,不定期更新技巧前端掘金技巧,偶爾更新。計算數組的極值技巧使你的更加專業前端掘金一個幫你提升技巧的收藏集。 CSS 樣式畫各種圖形 - 前端 - 掘金下面是一些我在 CSS 中經常用到的圖案,還有一些是在css-tricks看到的。記錄一下,以后會用到。會持續更新… 一、...
閱讀 2676·2021-11-16 11:53
閱讀 2737·2021-07-26 23:38
閱讀 2073·2019-08-30 15:55
閱讀 1751·2019-08-30 13:21
閱讀 3650·2019-08-29 17:26
閱讀 3306·2019-08-29 13:20
閱讀 875·2019-08-29 12:20
閱讀 3192·2019-08-26 10:21