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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java实现 二叉搜索树算法(BST)

發(fā)布時(shí)間:2025/3/21 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java实现 二叉搜索树算法(BST) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、樹 & 二叉樹

是由節(jié)點(diǎn)和邊構(gòu)成,儲(chǔ)存元素的集合。節(jié)點(diǎn)分根節(jié)點(diǎn)、父節(jié)點(diǎn)和子節(jié)點(diǎn)的概念。
如圖:樹深=4; 5是根節(jié)點(diǎn);同樣8與3的關(guān)系是父子節(jié)點(diǎn)關(guān)系。


二叉樹binary tree,則加了“二叉”(binary),意思是在樹中作區(qū)分。每個(gè)節(jié)點(diǎn)至多有兩個(gè)子(child),left child & right child。二叉樹在很多例子中使用,比如二叉樹表示算術(shù)表達(dá)式。
如圖:1/8是左節(jié)點(diǎn);2/3是右節(jié)點(diǎn);

二、二叉搜索樹 BST

顧名思義,二叉樹上又加了個(gè)搜索的限制。其要求:每個(gè)節(jié)點(diǎn)比其左子樹元素大,比其右子樹元素小。
如圖:每個(gè)節(jié)點(diǎn)比它左子樹的任意節(jié)點(diǎn)大,而且比它右子樹的任意節(jié)點(diǎn)小

三、BST Java實(shí)現(xiàn)

直接上代碼,對(duì)應(yīng)代碼分享在?Github?主頁
BinarySearchTree.java

package org.algorithm.tree; /** Copyright [2015] [Jeff Lee]** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*//*** 二叉搜索樹(BST)實(shí)現(xiàn)** Created by bysocket on 16/7/7.*/ public class BinarySearchTree {/*** 根節(jié)點(diǎn)*/public static TreeNode root;public BinarySearchTree() {this.root = null;}/*** 查找* 樹深(N) O(lgN)* 1. 從root節(jié)點(diǎn)開始* 2. 比當(dāng)前節(jié)點(diǎn)值小,則找其左節(jié)點(diǎn)* 3. 比當(dāng)前節(jié)點(diǎn)值大,則找其右節(jié)點(diǎn)* 4. 與當(dāng)前節(jié)點(diǎn)值相等,查找到返回TRUE* 5. 查找完畢未找到,* @param key* @return*/public TreeNode search (int key) {TreeNode current = root;while (current != null&& key != current.value) {if (key < current.value )current = current.left;elsecurrent = current.right;}return current;}/*** 插入* 1. 從root節(jié)點(diǎn)開始* 2. 如果root為空,root為插入值* 循環(huán):* 3. 如果當(dāng)前節(jié)點(diǎn)值大于插入值,找左節(jié)點(diǎn)* 4. 如果當(dāng)前節(jié)點(diǎn)值小于插入值,找右節(jié)點(diǎn)* @param key* @return*/public TreeNode insert (int key) {// 新增節(jié)點(diǎn)TreeNode newNode = new TreeNode(key);// 當(dāng)前節(jié)點(diǎn)TreeNode current = root;// 上個(gè)節(jié)點(diǎn)TreeNode parent = null;// 如果根節(jié)點(diǎn)為空if (current == null) {root = newNode;return newNode;}while (true) {parent = current;if (key < current.value) {current = current.left;if (current == null) {parent.left = newNode;return newNode;}} else {current = current.right;if (current == null) {parent.right = newNode;return newNode;}}}}/*** 刪除節(jié)點(diǎn)* 1.找到刪除節(jié)點(diǎn)* 2.如果刪除節(jié)點(diǎn)左節(jié)點(diǎn)為空 , 右節(jié)點(diǎn)也為空;* 3.如果刪除節(jié)點(diǎn)只有一個(gè)子節(jié)點(diǎn) 右節(jié)點(diǎn) 或者 左節(jié)點(diǎn)* 4.如果刪除節(jié)點(diǎn)左右子節(jié)點(diǎn)都不為空* @param key* @return*/public TreeNode delete (int key) {TreeNode parent = root;TreeNode current = root;boolean isLeftChild = false;// 找到刪除節(jié)點(diǎn) 及 是否在左子樹while (current.value != key) {parent = current;if (current.value > key) {isLeftChild = true;current = current.left;} else {isLeftChild = false;current = current.right;}if (current == null) {return current;}}// 如果刪除節(jié)點(diǎn)左節(jié)點(diǎn)為空 , 右節(jié)點(diǎn)也為空if (current.left == null && current.right == null) {if (current == root) {root = null;}// 在左子樹if (isLeftChild == true) {parent.left = null;} else {parent.right = null;}}// 如果刪除節(jié)點(diǎn)只有一個(gè)子節(jié)點(diǎn) 右節(jié)點(diǎn) 或者 左節(jié)點(diǎn)else if (current.right == null) {if (current == root) {root = current.left;} else if (isLeftChild) {parent.left = current.left;} else {parent.right = current.left;}}else if (current.left == null) {if (current == root) {root = current.right;} else if (isLeftChild) {parent.left = current.right;} else {parent.right = current.right;}}// 如果刪除節(jié)點(diǎn)左右子節(jié)點(diǎn)都不為空else if (current.left != null && current.right != null) {// 找到刪除節(jié)點(diǎn)的后繼者TreeNode successor = getDeleteSuccessor(current);if (current == root) {root = successor;} else if (isLeftChild) {parent.left = successor;} else {parent.right = successor;}successor.left = current.left;}return current;}/*** 獲取刪除節(jié)點(diǎn)的后繼者* 刪除節(jié)點(diǎn)的后繼者是在其右節(jié)點(diǎn)樹種最小的節(jié)點(diǎn)* @param deleteNode* @return*/public TreeNode getDeleteSuccessor(TreeNode deleteNode) {// 后繼者TreeNode successor = null;TreeNode successorParent = null;TreeNode current = deleteNode.right;while (current != null) {successorParent = successor;successor = current;current = current.left;}// 檢查后繼者(不可能有左節(jié)點(diǎn)樹)是否有右節(jié)點(diǎn)樹// 如果它有右節(jié)點(diǎn)樹,則替換后繼者位置,加到后繼者父親節(jié)點(diǎn)的左節(jié)點(diǎn).if (successor != deleteNode.right) {successorParent.left = successor.right;successor.right = deleteNode.right;}return successor;}public void toString(TreeNode root) {if (root != null) {toString(root.left);System.out.print("value = " + root.value + " -> ");toString(root.right);}} }/*** 節(jié)點(diǎn)*/ class TreeNode {/*** 節(jié)點(diǎn)值*/int value;/*** 左節(jié)點(diǎn)*/TreeNode left;/*** 右節(jié)點(diǎn)*/TreeNode right;public TreeNode(int value) {this.value = value;left = null;right = null;} }

1.?節(jié)點(diǎn)數(shù)據(jù)結(jié)構(gòu)
首先定義了節(jié)點(diǎn)的數(shù)據(jù)接口,節(jié)點(diǎn)分左節(jié)點(diǎn)和右節(jié)點(diǎn)及本身節(jié)點(diǎn)值。如圖

代碼如下:

/*** 節(jié)點(diǎn)*/ class TreeNode {/*** 節(jié)點(diǎn)值*/int value;/*** 左節(jié)點(diǎn)*/TreeNode left;/*** 右節(jié)點(diǎn)*/TreeNode right;public TreeNode(int value) {this.value = value;left = null;right = null;} }

?

2. 插入
插入,和刪除一樣會(huì)引起二叉搜索樹的動(dòng)態(tài)變化。插入相對(duì)刪處理邏輯相對(duì)簡單些。如圖插入的邏輯:


a. 從root節(jié)點(diǎn)開始
b.如果root為空,root為插入值
c.循環(huán):
d.如果當(dāng)前節(jié)點(diǎn)值大于插入值,找左節(jié)點(diǎn)
e.如果當(dāng)前節(jié)點(diǎn)值小于插入值,找右節(jié)點(diǎn)
代碼對(duì)應(yīng):

/*** 插入* 1. 從root節(jié)點(diǎn)開始* 2. 如果root為空,root為插入值* 循環(huán):* 3. 如果當(dāng)前節(jié)點(diǎn)值大于插入值,找左節(jié)點(diǎn)* 4. 如果當(dāng)前節(jié)點(diǎn)值小于插入值,找右節(jié)點(diǎn)* @param key* @return*/public TreeNode insert (int key) {// 新增節(jié)點(diǎn)TreeNode newNode = new TreeNode(key);// 當(dāng)前節(jié)點(diǎn)TreeNode current = root;// 上個(gè)節(jié)點(diǎn)TreeNode parent = null;// 如果根節(jié)點(diǎn)為空if (current == null) {root = newNode;return newNode;}while (true) {parent = current;if (key < current.value) {current = current.left;if (current == null) {parent.left = newNode;return newNode;}} else {current = current.right;if (current == null) {parent.right = newNode;return newNode;}}}}

?

3.查找

其算法復(fù)雜度 :?O(lgN),樹深(N)。如圖查找邏輯:


a.從root節(jié)點(diǎn)開始
b.比當(dāng)前節(jié)點(diǎn)值小,則找其左節(jié)點(diǎn)
c.比當(dāng)前節(jié)點(diǎn)值大,則找其右節(jié)點(diǎn)
d.與當(dāng)前節(jié)點(diǎn)值相等,查找到返回TRUE
e.查找完畢未找到
代碼對(duì)應(yīng):

/*** 查找* 樹深(N) O(lgN)* 1. 從root節(jié)點(diǎn)開始* 2. 比當(dāng)前節(jié)點(diǎn)值小,則找其左節(jié)點(diǎn)* 3. 比當(dāng)前節(jié)點(diǎn)值大,則找其右節(jié)點(diǎn)* 4. 與當(dāng)前節(jié)點(diǎn)值相等,查找到返回TRUE* 5. 查找完畢未找到,* @param key* @return*/public TreeNode search (int key) {TreeNode current = root;while (current != null&& key != current.value) {if (key < current.value )current = current.left;elsecurrent = current.right;}return current;}

4. 刪除
首先找到刪除節(jié)點(diǎn),其尋找方法:刪除節(jié)點(diǎn)的后繼者是在其右節(jié)點(diǎn)樹種最小的節(jié)點(diǎn)。如圖刪除對(duì)應(yīng)邏輯:

結(jié)果為:


a.找到刪除節(jié)點(diǎn)
b.如果刪除節(jié)點(diǎn)左節(jié)點(diǎn)為空 , 右節(jié)點(diǎn)也為空;
c.如果刪除節(jié)點(diǎn)只有一個(gè)子節(jié)點(diǎn) 右節(jié)點(diǎn) 或者 左節(jié)點(diǎn)
d.如果刪除節(jié)點(diǎn)左右子節(jié)點(diǎn)都不為空
代碼對(duì)應(yīng)見上面完整代碼。

?

案例測試代碼如下,BinarySearchTreeTest.java

package org.algorithm.tree; /** Copyright [2015] [Jeff Lee]** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*//*** 二叉搜索樹(BST)測試案例 {@link BinarySearchTree}** Created by bysocket on 16/7/10.*/ public class BinarySearchTreeTest {public static void main(String[] args) {BinarySearchTree b = new BinarySearchTree();b.insert(3);b.insert(8);b.insert(1);b.insert(4);b.insert(6);b.insert(2);b.insert(10);b.insert(9);b.insert(20);b.insert(25);// 打印二叉樹b.toString(b.root);System.out.println();// 是否存在節(jié)點(diǎn)值10TreeNode node01 = b.search(10);System.out.println("是否存在節(jié)點(diǎn)值為10 => " + node01.value);// 是否存在節(jié)點(diǎn)值11TreeNode node02 = b.search(11);System.out.println("是否存在節(jié)點(diǎn)值為11 => " + node02);// 刪除節(jié)點(diǎn)8TreeNode node03 = b.delete(8);System.out.println("刪除節(jié)點(diǎn)8 => " + node03.value);b.toString(b.root);} }

運(yùn)行結(jié)果如下:

value = 1 -> value = 2 -> value = 3 -> value = 4 -> value = 6 -> value = 8 -> value = 9 -> value = 10 -> value = 20 -> value = 25 -> 是否存在節(jié)點(diǎn)值為10 => 10 是否存在節(jié)點(diǎn)值為11 => null 刪除節(jié)點(diǎn)8 => 8 value = 1 -> value = 2 -> value = 3 -> value = 4 -> value = 6 -> value = 9 -> value = 10 -> value = 20 -> value = 25 ->

四、小結(jié)

與偶爾吃一碗“老壇酸菜牛肉面”一樣的味道,品味一個(gè)算法,比如BST,的時(shí)候,總是那種說不出的味道。

樹,二叉樹的概念

BST算法

相關(guān)代碼分享在?Github?主頁


轉(zhuǎn)載自并發(fā)編程網(wǎng) – ifeve.com本文鏈接地址:?Java實(shí)現(xiàn) 二叉搜索樹算法(BST)

總結(jié)

以上是生活随笔為你收集整理的Java实现 二叉搜索树算法(BST)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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