Java實(shí)現(xiàn)二分搜索樹的示例代碼
1.概念
a.是個(gè)二叉樹(每個(gè)節(jié)點(diǎn)最多有兩個(gè)子節(jié)點(diǎn))
b.對(duì)于這棵樹中的節(jié)點(diǎn)的節(jié)點(diǎn)值
左子樹中的所有節(jié)點(diǎn)值 < 根節(jié)點(diǎn) < 右子樹的所有節(jié)點(diǎn)值
二分搜索樹中一般不考慮值相等的情況(元素不重復(fù))JDK中的搜索樹就不存在相同的值(TreeMap-key)

最大特點(diǎn):也是判斷是否是搜索樹的方法
對(duì)該樹進(jìn)行中序遍歷,就可以得到一個(gè)升序集合0 1 2 3 4 5 6 7 8 9
在一個(gè)有序區(qū)間上進(jìn)行二分查找的時(shí)間復(fù)雜度? logn不斷將集合/2/2 / 2 ==1為止logN
logN =》聯(lián)想到"樹"
2.重點(diǎn)操作

當(dāng)刪除58時(shí),此節(jié)點(diǎn)左右子樹都不為空
Hibbard Deletion 1962
在BST中刪除一個(gè)左右子樹都存在的節(jié)點(diǎn)
找到當(dāng)前以58為根節(jié)點(diǎn)的前驅(qū)或者后繼節(jié)點(diǎn)作為刪除后的新節(jié)點(diǎn)
前驅(qū):在以58為根的BST中最后一個(gè)小于58的節(jié)點(diǎn)->53
后繼:在以58為根的BST中第一個(gè)大于58的節(jié)點(diǎn)->59
當(dāng)我們使用后繼節(jié)點(diǎn)時(shí),先連removeMin(root.right),在連root.left
TreeNode successor = findMin(root.right); successor.right = removeMin(root.right); successor.left = root.left;
3.完整代碼
import java.util.NoSuchElementException;
/**
* 基于整型的
* 普通的二分搜索樹
*/
public class BST {
private class TreeNode{
private int val;
private TreeNode left;
private TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
private int size;
private TreeNode root;
/**
* 向以root為根的BST中插入一個(gè)新的結(jié)點(diǎn)val
* @param val
*/
public void add(int val){
root = add(root,val);
}
private TreeNode add(TreeNode root, int val) {
if(root == null){
//創(chuàng)建一個(gè)新節(jié)點(diǎn)
TreeNode newNode = new TreeNode(val);
size++;
return newNode;
}
//左子樹插入
if(val < root.val){
root.left = add(root.left,val);
}
//右子樹插入
if(val > root.val){
root.right = add(root.right,val);
}
return root;
}
/**
* 判斷當(dāng)前以root為根的BST中是否包含了val
* @param val
* @return
*/
public boolean contains(int val){
return contains(root,val);
}
private boolean contains(TreeNode root, int val) {
if(root == null){
return false;
}
if(val == root.val){
//找到了
return true;
}else if(val < root.val){
//遞歸左子樹查找
return contains(root.left,val);
}else{
//遞歸右子樹查找
return contains(root.right,val);
}
}
/**
* 找到最小值
* @return
*/
public int findMin(){
//判空
if(root == null){
//拋出一個(gè)空指針異常
throw new NoSuchElementException("root is empty! cannot find min");
}
TreeNode minNode = findMin(root);
return minNode.val;
}
private TreeNode findMin(TreeNode root) {
//當(dāng)此節(jié)點(diǎn)左子樹為空,說明此節(jié)點(diǎn)是最小值
if(root.left == null){
return root;
}
//遞歸訪問左子樹
return findMin(root.left);
}
/**
* 找到最大值
* @return
*/
public int findMax(){
//判空
if(root == null){
throw new NoSuchElementException("root is empty! cannot find max");
}
TreeNode maxNode = findMax(root);
return maxNode.val;
}
private TreeNode findMax(TreeNode root) {
//當(dāng)此節(jié)點(diǎn)右子樹為空,說明此節(jié)點(diǎn)是最大值
if(root.right == null){
return root;
}
//遞歸訪問右子樹
return findMax(root.right);
}
/**
* 在當(dāng)前BST中刪除最小值節(jié)點(diǎn),返回刪除的最小值
* @return
*/
public int removeMin(){
int min =findMin();
root = removeMin(root);
return min;
}
private TreeNode removeMin(TreeNode root) {
if(root.left == null){
TreeNode right = root.right;
//找到最小值,刪除節(jié)點(diǎn)
root = root.left = null;
size--;
return right;
}
root.left = removeMin(root.left);
return root;
}
/**
* 在當(dāng)前BST中刪除最大值節(jié)點(diǎn),返回刪除的最大值
* @return
*/
public int removeMax(){
int max = findMax();
root = removeMax(root);
return max;
}
//在當(dāng)前以root為根的BST中刪除最小值所在的節(jié)點(diǎn),返回刪除后的樹根
private TreeNode removeMax(TreeNode root) {
if(root.right == null){
TreeNode right = root.right;
//找到最大值,刪除節(jié)點(diǎn)
root = root.right = null;
size--;
return right;
}
root.right = findMax(root.right);
return root;
}
/**
* 在當(dāng)前以root為根節(jié)點(diǎn)的BST中刪除值為val的節(jié)點(diǎn)
* 返回刪除后的新的根節(jié)點(diǎn)
* @return
*/
public void removeValue(int value){
root = removeValue(root,value);
}
private TreeNode removeValue(TreeNode root, int value) {
if(root == null){
throw new NoSuchElementException("root is empty! cannot find remove");
}else if(value < root.val){
root.left = removeValue(root.left,value);
return root;
}else if(value > root.val){
root.right = removeValue(root.right,value);
return root;
}else {
//此時(shí)value == root.value
if(root.left == null){
//刪除最小數(shù)
TreeNode right = root.right;
root = root.right = null;
size--;
return right;
}
if(root.right == null){
//刪除最大數(shù)
TreeNode left = root.left;
root = root.left =null;
size--;
return left;
}
//找到當(dāng)前該刪除節(jié)點(diǎn)的前驅(qū)或者后繼節(jié)點(diǎn)作為刪除后的新節(jié)點(diǎn)
//當(dāng)我們使用后繼節(jié)點(diǎn)時(shí),先連removeMin(root.right),在連root.left
TreeNode successor = findMin(root.right);
successor.right = removeMin(root.right);
successor.left = root.left;
return successor;
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
generateBSTString(root,0,sb);
return sb.toString();
}
//直觀打印,可以看到樹的深度
private void generateBSTString(TreeNode root, int height, StringBuilder sb) {
if(root == null){
sb.append(generateHeightString(height)).append("NULL\n");
return;
}
sb.append(generateHeightString(height)).append(root.val).append("\n");
generateBSTString(root.left,height+1,sb);
generateBSTString(root.right,height+1,sb);
}
private String generateHeightString(int height) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < height; i++) {
sb.append("--");
}
return sb.toString();
}
}到此這篇關(guān)于Java實(shí)現(xiàn)二分搜索樹的示例代碼的文章就介紹到這了,更多相關(guān)Java二分搜索樹內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Thread多線程開發(fā)中Object類詳細(xì)講解
這篇文章主要介紹了Java Thread多線程開發(fā)中Object類,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-03-03
Flowable數(shù)據(jù)庫表分類及數(shù)據(jù)字典解析
這篇文章主要介紹了Flowable數(shù)據(jù)庫表分類及數(shù)據(jù)字典解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
Spring Boot多數(shù)據(jù)源及其事務(wù)管理配置方法
本篇文章主要介紹了Spring Boot多數(shù)據(jù)源及其事務(wù)管理配置方法,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-04-04
MyBatis實(shí)現(xiàn)動(dòng)態(tài)SQL的實(shí)現(xiàn)方法
這篇文章主要介紹了MyBatis實(shí)現(xiàn)動(dòng)態(tài)SQL的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
SpringBoot+RabbitMq具體使用的幾種姿勢(shì)
這篇文章主要介紹了SpringBoot+RabbitMq具體使用的幾種姿勢(shì),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
Java中動(dòng)態(tài)地改變數(shù)組長(zhǎng)度及數(shù)組轉(zhuǎn)Map的代碼實(shí)例分享
這篇文章主要介紹了Java中動(dòng)態(tài)地改變數(shù)組長(zhǎng)度及數(shù)組轉(zhuǎn)map的代碼分享,其中轉(zhuǎn)Map利用到了java.util.Map接口,需要的朋友可以參考下2016-03-03

