日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

js实现数据结构及算法之二叉树(Binary Tree)

發(fā)布時間:2025/7/14 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js实现数据结构及算法之二叉树(Binary Tree) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

樹(Tree)

樹是一種非線性的數(shù)據(jù)結構,分層存儲

樹常被用來存儲具有層級關系的數(shù)據(jù),也會被用來存儲有序列表等

樹和集合一樣,不允許相同的元素存在

樹由一組以邊連接的節(jié)點組成

一棵樹最上面的節(jié)點稱為根節(jié)點,如果一個節(jié)點下面連接多個節(jié)點,那么該節(jié)點稱為父節(jié)點,它下面的節(jié)點被稱為子節(jié)點。一個節(jié)點可以有0個、1個或多個子節(jié)點。沒有任何子節(jié)點的節(jié)點稱為葉子節(jié)點

二叉樹(Binary Tree)

二叉樹是一種特殊的樹,子節(jié)點個數(shù)不超過兩個,且分別稱為該結點的左子樹(left subtree)與右子樹(right subtree)

? ? ? ? ? ? ? ?

二叉查找樹(BST)

二叉查找樹是一種特殊的二叉樹,相對較小的值保存在左節(jié)點,較大的值保存在右節(jié)點,這一特性使得查找效率很高

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

完全二叉樹

若設二叉樹的高度為h,除第 h 層外,其它各層 (1~h-1) 的結點數(shù)都達到最大個數(shù),第h層有葉子結點,并且葉子結點都是從左到右依次排布,這就是完全二叉樹

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??


滿二叉樹

除了葉結點外每一個結點都有左右子葉且葉子結點都處在最底層的二叉樹


平衡二叉樹(AVL樹)

它是一棵二叉排序樹,且具有以下性質(zhì):它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,并且左右兩個子樹都是一棵平衡二叉樹

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

二叉樹遍歷

按一定的規(guī)則和順序走遍二叉樹的所有結點,使每一個結點都被訪問一次,而且只被訪問一次,這個操作被稱為樹的遍歷,是對樹的一種最基本的運算。

按照根節(jié)點訪問的順序不同,樹的遍歷分為以下三種:前序遍歷,中序遍歷,后序遍歷;

前序遍歷:根節(jié)點->左子樹->右子樹


23->16->22->45->37->99

中序遍歷:左子樹->根節(jié)點->右子樹


16->22->23->37->45->99

后序遍歷:左子樹->右子樹->根節(jié)點


22->16->37->99->45->23

決定是先中后遍歷的根節(jié)點的遍歷位置,若根節(jié)點是第一個遍歷,便是先序遍歷;若根節(jié)點是第二個遍歷,便是中序遍歷;若根節(jié)點是最后一個遍歷,便是后序遍歷

js二叉查找樹(BST)

實現(xiàn)二叉樹的難點,是插入與刪除,需要注意,如果使用中序遍歷,便是排序了

/*** 一個簡單的二叉查找樹(BST)* @constructor*///節(jié)點定義function Node(data, left, right) {this.data = data; // 數(shù)據(jù)this.left = left; // 左節(jié)點this.right = right; // 右節(jié)點this.show = show; // 顯示節(jié)點數(shù)據(jù)}//二叉樹類function BST() {this.root = null; // 根節(jié)點this.insert = insert; // 插入節(jié)點this.preOrder = preOrder; // 先序遍歷this.inOrder = inOrder; // 中序遍歷this.postOrder = postOrder; // 后序遍歷this.find = find; // 查找節(jié)點this.getMin = getMin; // 查找最小值this.getMax = getMax; // 查找最大值this.remove = remove; // 刪除節(jié)點this.removeNode = removeNode; // 刪除節(jié)點}//顯示節(jié)點數(shù)據(jù)function show() {return this.data}//插入節(jié)點/*首先要添加新的節(jié)點,首先需要創(chuàng)建一個Node對象,將數(shù)據(jù)傳入該對象。其次要檢查當前的BST樹是否有根節(jié)點,如果沒有,那么表示是一棵新數(shù),該節(jié)點就為該樹的根節(jié)點,那么插入這個過程就結束了;否則,就要繼續(xù)進行下一步了。如果待插入節(jié)點不是根節(jié)點,那么就必須對BST進行遍歷,找到合適的位置。該過程類似遍歷鏈表,用一個變量存儲當前節(jié)點,一層一層遍歷BST,算法如下:1.設值當前節(jié)點為根節(jié)點2.如果待插入節(jié)點保存的數(shù)據(jù)小于當前節(jié)點,則新節(jié)點為原節(jié)點的左節(jié)點,反之,執(zhí)行第4步3.如果當前節(jié)點的左節(jié)點為null,就將新節(jié)點放到這個位置,退出循環(huán);反之,繼續(xù)執(zhí)行下一次循環(huán)4.設置新節(jié)點為原節(jié)點的右節(jié)點5.如果當前節(jié)點的右節(jié)點為null,就將新節(jié)點放到這個位置,退出循環(huán);反之,繼續(xù)執(zhí)行下一次循環(huán) */function insert(data) {var n = new Node(data, null, null)if (this.root === null) {this.root = n} else {var current = this.rootvar parentwhile (true) {parent = currentif (data < current.data) {current = current.leftif (current === null) {parent.left = nbreak}} else {current = current.rightif (current === null) {parent.right = nbreak}}}}}//先序遍歷function preOrder(node) {if (node !== null) {console.log(node.show())preOrder(node.left)preOrder(node.right)}}//中序遍歷function inOrder(node) {if (node !== null) {inOrder(node.left)console.log(node.show())inOrder(node.right)}}//后序遍歷function postOrder(node) {if (node !== null) {postOrder(node.left)postOrder(node.right)console.log(node.show())}}//查找節(jié)點function find(data) {var current = this.rootwhile (current !== null) {if (current.data === data) {return current} else if (data < current.data) {current = current.left} else {current = current.right}}return null}//查找最小值function getMin(root) {var current = this.root || rootwhile (current.left !== null) {current = current.left}return current}//查找最大值function getMax(root) {var current = this.root || rootwhile (current.right !== null) {current = current.right}return current} /* 從BST中刪除節(jié)點的操作最為復雜,其復雜程度取決于刪除的節(jié)點位置。 如果待刪除的節(jié)點沒有子節(jié)點,那么非常簡單。 如果刪除包含左子節(jié)點或者右子節(jié)點,就變得稍微有些復雜。如果刪除包含兩個節(jié)點的節(jié)點最為復雜。 我們采用遞歸方法,來完成復雜的刪除操作,我們定義 remove() 和 removeNode() 兩個方法; 算法思想如下: 1.判斷當前節(jié)點是否包含待刪除的數(shù)據(jù),如果包含,則刪除該節(jié)點; 2.如果不包含,則比較當前節(jié)點上的數(shù)據(jù)和待刪除樹的的大小關系。 3.如果待刪除的數(shù)據(jù)小于當前節(jié)點的數(shù)據(jù),則移至當前節(jié)點的左子節(jié)點繼續(xù)比較; 4.如果大于,則移至當前節(jié)點的右子節(jié)點繼續(xù)比較。 5.如果待刪除節(jié)點是葉子節(jié)點(沒有子節(jié)點),那么只需要將從父節(jié)點指向它的鏈接指向變?yōu)閚ull; 6.如果待刪除節(jié)點含有一個子節(jié)點,那么原本指向它的節(jié)點需要做調(diào)整,使其指向它的子節(jié)點; 7.最后,如果待刪除節(jié)點包含兩個子節(jié)點,可以選擇查找待刪除節(jié)點左子樹上的最大值或者查找其右子樹上的最小值, 這里我們選擇后一種。 因此,我們需要一個查找樹上最小值的方法,后面會用它找到最小值創(chuàng)建一個臨時節(jié)點, 將臨時節(jié)點上的值復制到待刪除節(jié)點,然后再刪除臨時節(jié)點; *///刪除操作function remove(data) {this.removeNode(this.root, data)}// 刪除節(jié)點function removeNode(node, data) {if (node === null) return nullif (data === node.data) {if (node.left === null && node.right === null) {return null}if (node.left === null) {return node.right}if (node.right === null) {return node.left}var tempNode = getMin(node.right)node.data = tempNode.datanode.right = removeNode(node.right, tempNode.data)return node} else if (data > node.data) {node.right = removeNode(node.right, data)return node} else {node.left = removeNode(node.left, data)return node}}var bst = new BST()bst.insert(23);bst.insert(45);bst.insert(16);bst.insert(37);bst.insert(99);bst.insert(22);console.log('=====先序======')bst.preOrder(bst.root)console.log('=====中序======')bst.inOrder(bst.root)console.log('=====后序======')bst.postOrder(bst.root)console.log('=====remove======')bst.remove(23)console.log(bst)console.log('最小值->' + bst.getMin(bst.root))console.log('最大值->' + bst.getMax(bst.root))復制代碼


總結

以上是生活随笔為你收集整理的js实现数据结构及算法之二叉树(Binary Tree)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。