摘要:二叉搜索樹這一數(shù)據(jù)結(jié)構(gòu)綜合了以上兩種數(shù)據(jù)結(jié)構(gòu)的優(yōu)點(diǎn)。上圖就展示了一個(gè)二叉搜索樹。實(shí)現(xiàn)二叉樹的算法大部分都有遞歸。
樹
一種非順序數(shù)據(jù)結(jié)構(gòu)-樹,它對于存儲(chǔ)需要快速查找的數(shù)據(jù)非常有用
相關(guān)概念:
根節(jié)點(diǎn):位于樹頂部的節(jié)點(diǎn),沒有父節(jié)點(diǎn)
內(nèi)部節(jié)點(diǎn):至少有一個(gè)子節(jié)點(diǎn)的節(jié)點(diǎn)(7,5,9,15,13,20)
外部節(jié)點(diǎn)(葉節(jié)點(diǎn)):沒有子元素的節(jié)點(diǎn)(第3層)
子樹:由節(jié)點(diǎn)和它的后代構(gòu)成(節(jié)點(diǎn)13,12,14構(gòu)成了一個(gè)子樹)
深度:節(jié)點(diǎn)的深度取決于它的祖先節(jié)點(diǎn)的數(shù)量
高度:取決于所有節(jié)點(diǎn)深度的最大值
二叉搜索樹(BST)無序鏈表在插入時(shí)候具有較高的靈敏性,而有序數(shù)組在查找的時(shí)候具有較高的效率。
二叉搜索樹(BST)這一數(shù)據(jù)結(jié)構(gòu)綜合了以上兩種數(shù)據(jù)結(jié)構(gòu)的優(yōu)點(diǎn)。但是它只允許你在左側(cè)節(jié)點(diǎn)存儲(chǔ)(比父節(jié)點(diǎn))小的值,右側(cè)節(jié)點(diǎn)存儲(chǔ)(比父節(jié)點(diǎn))大的值。
上圖就展示了一個(gè)二叉搜索樹。實(shí)現(xiàn)二叉樹的算法大部分都有遞歸。
創(chuàng)建一個(gè)BinarySearchTree類
function BinarySearchTree () { var Node = function () { this.key = key; // 鍵 this.left = null; // 指針指向左側(cè)子節(jié)點(diǎn) this.right = null; // 指針指向右側(cè)子節(jié)點(diǎn) }; var root = null; } var tree = new BinarySearchTree();
實(shí)現(xiàn)insert(key)方法,插入一個(gè)鍵
this.insert = function (key) { var newNode = new Node(kye); // 創(chuàng)建用來表示新節(jié)點(diǎn)的Node類實(shí)例, if (root === null) { // 如果插入的節(jié)點(diǎn)是樹第一個(gè)節(jié)點(diǎn) root = newNode; } else { insertNode(root, newNode); // 私有的輔助函數(shù) } } tree.insert();
私有的輔助函數(shù)
var insertNode = function (node, newNode) { // 從根節(jié)點(diǎn)開始 if (newNode.key < node.key) { // 判斷左側(cè),遍歷左側(cè) if (node.left === null) { // 如果子節(jié)點(diǎn)為空,就在子節(jié)點(diǎn)添加新節(jié)點(diǎn) node.left = newNode; } else { insertNode(node.left, newNode); // 往下遞歸 } } else { // 判斷右側(cè),遍歷右側(cè) if (node.right === null) { node.right = newNode; } else { insertNode(node.right, newNode); } } }二叉樹的遍歷
前序遍歷:根節(jié)點(diǎn)->左子樹->右子樹
中序遍歷:左子樹->根節(jié)點(diǎn)->右子樹
后序遍歷:左子樹->右子樹->根節(jié)點(diǎn)
對下面的樹進(jìn)行遍歷
前序遍歷:abdefgc
中序遍歷:debgfac
后序遍歷:edgfbca
中序遍歷:一種應(yīng)用是對樹進(jìn)行排序操作
this.inOrderTraverse = function {callback} { inOrderTraverse(root, callback); // 回調(diào)函數(shù)用來處理遍歷到的每個(gè)節(jié)點(diǎn) };
var inOrderTraverseNode = function (node, callback) { if (node !== null) { inOrderTraverseNode(node.left, callback); callback(node.key); inOrderTraverseNode(node.right, callback); } }
先序遍歷:一種應(yīng)用是打印一個(gè)結(jié)構(gòu)化的文檔
this.preOrderTraverse = function (callback) { preOrderTraverseNode(root, callback); } var preOrderTraverseNode = function (node, callback) { if (node !== null) { callback(node.key); preOrderTraverseNode(node.left, callback); preOrderTraverseNode(node.right, callback); } }
后序遍歷:一種應(yīng)用是計(jì)算一個(gè)目錄和它的子目錄中所有文件所占的空間大小。
this.postOrderTraverse = function (callback) { postOrderTraverse(root, callback); } var postOrderTraverse = function (callback) { if (node !== null) { postOrderTraverse(node.left, callback); postOrderTraverse(node.right, callback); callback(node.key); } }搜索樹中的值
對于尋找最小值,總是沿著樹的左邊;對于尋找最大值,總是沿著樹的右邊
尋找樹中的最小鍵
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; }
尋找一個(gè)特定的值
this.search = function (key) { return searchNode(root, key); } var searchNode = function (node, kye) { if (node === null) { // node有效性檢查 return false; } if (key < node.key) { // 比當(dāng)前節(jié)點(diǎn)小,當(dāng)前節(jié)點(diǎn)的左側(cè)子樹搜索 return searchNode(node.left, key); } else if (key > node.key) { // 比當(dāng)前節(jié)點(diǎn)大,當(dāng)前節(jié)點(diǎn)的右側(cè)子樹搜索 return searchNode(node.right, key); } else { // 要找的鍵就是當(dāng)前節(jié)點(diǎn) return true; } }移除一個(gè)節(jié)點(diǎn)
this.remove = function (key) { root = removeNode (root, key); } var removeNode = function (node, key) { if (node === null) { // 鍵不存在于樹中 return null; } if (key < node.key) { node.left = removeNode(node.left, key); return node; } else if (key > node.key) { node.right = removeNode(node.right, key); return node; } else { if (node.left === null && node.right === null) { // 一個(gè)葉節(jié)點(diǎn) node = null; return node; } if (node.left === null) { // 一個(gè)只有一個(gè)子節(jié)點(diǎn)的節(jié)點(diǎn) node = node.right; return node; } else if (node.right === null) { node = node.left; return node; } // 一個(gè)有兩個(gè)子節(jié)點(diǎn)的節(jié)點(diǎn) var aux = findMinNode(node.right); node.key = aux.key; node.right = removeNode(node.right, aux.key); return node; } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/82448.html
摘要:二叉搜索樹的特性二叉搜索樹由于其獨(dú)特的數(shù)據(jù)結(jié)構(gòu),使得其無論在增刪,還是查找,時(shí)間復(fù)雜度都是,為二叉樹的高度。二叉搜索樹的查找查找很簡單,根據(jù)左子節(jié)點(diǎn)比該節(jié)點(diǎn)小,右子節(jié)點(diǎn)比該節(jié)點(diǎn)大的原則進(jìn)行循環(huán)判斷即可。 什么是二叉樹 二叉樹就是樹的每個(gè)節(jié)點(diǎn)最多只能有兩個(gè)子節(jié)點(diǎn) 什么是二叉搜索樹 二叉搜索樹在二叉樹的基礎(chǔ)上,多了一個(gè)條件,就是二叉樹在插入值時(shí),若插入值比當(dāng)前節(jié)點(diǎn)小,就插入到左節(jié)點(diǎn),否則插...
摘要:我對字典的簡單學(xué)習(xí)字典的概念集合字典和散列表都可以來存儲(chǔ)不重復(fù)的值。字典也被稱為映射。中有集合類的實(shí)現(xiàn),也有字典類的實(shí)現(xiàn)。相關(guān)操作方法實(shí)現(xiàn)方法,判斷某個(gè)鍵值是否在這個(gè)字典中,有則返回。實(shí)現(xiàn)方法,將字典所有的值以數(shù)組的形式返回。 我對JS字典的簡單學(xué)習(xí) 字典的概念 集合、字典和散列表都可以來存儲(chǔ)不重復(fù)的值。在集合中我們使用[值,值]來保存,在字典和散列表中使用[鍵,值]來存儲(chǔ)數(shù)據(jù)。 字典...
摘要:我對棧的學(xué)習(xí)因?yàn)槭莻€(gè)新手,所以都是最簡單的知識(shí)學(xué)習(xí)梳理。棧是一種遵從后進(jìn)先出原則的有序集合,新添加的或者待刪除的元素都保留在棧的末尾,稱作棧頂,另一端叫做棧底。棧的學(xué)習(xí)棧的創(chuàng)建創(chuàng)建一個(gè)類來表示棧。對于棧來說只能用和方法來進(jìn)行添加和刪除元素。 我對棧的學(xué)習(xí) 因?yàn)槭莻€(gè)新手,所以都是最簡單的知識(shí)學(xué)習(xí)梳理。 什么是棧 數(shù)組是計(jì)算機(jī)科學(xué)中最常用的數(shù)據(jù)結(jié)構(gòu),是數(shù)據(jù)元素的集合。有時(shí)候我們需要一種添加...
閱讀 3859·2023-04-26 00:36
閱讀 2667·2021-11-16 11:44
閱讀 1082·2021-11-15 17:58
閱讀 1665·2021-09-30 09:47
閱讀 1208·2019-08-30 13:05
閱讀 1539·2019-08-30 12:55
閱讀 2409·2019-08-30 11:02
閱讀 2718·2019-08-29 17:01