描述
英文全称:Binary Sort Tree,它满足以下3个特点:
1.一个节点的左节点的值,一定小于它本身节点的值
2.一个节点的右节点的值,一定大于它本身节点的值
3.一个节点的左右子树,都属于排序二叉树
相关操作
1、树节点构造
class Node {
int data;
Node left;
Node right;
public Node() {
}
public Node(int data) {
this.data = data;
}
}
2、遍历树(中序遍历)
/**
* 中序遍历
*
* @param node
*/
private void travel(Node node) {
if (node == null) {
return;
}
travel(node.left);
System.out.print(node.data + " ");
travel(node.right);
}
3、添加节点
/**
* 添加节点
*
* @param data
*/
private void add(int data) {
Node newNode = new Node(data);
if (root == null) {
root = newNode;
return;
}
Node current = root;
while (true) {
if (current.data > data) {
if (current.left == null) {
current.left = newNode;
return;
}
current = current.left;
} else {
if (current.right == null) {
current.right = newNode;
return;
}
current = current.right;
}
}
}
4、寻找某个节点
/**
* 寻找某个节点
*
* @param value
* @return
*/
private Node findNode(int value) {
Node current = root;
while (true) {
if (current == null) {
return null;
}
if (current.data == value) {
return current;
}
if (current.data > value) {
current = current.left;
} else {
current = current.right;
}
}
}
5、删除操作
除了空树和待删除节点不存在以外,删除操作有以下3中情况:
- 待删除节点是叶子结点
直接删除
- 待删除节点拥有左子树或者右子树
直接删除,并向上拼接左子树或者右子树
- 待删除节点既有左子树又有右子树
找到中序排序下的前驱或者后驱节点(即是中序排序后,前后节点;这里寻找后节点,即是后驱节点),用它代替待删除节点
/**
* 删除某个节点(三种情况)
*
* @param value
* @return
*/
private Node del(int value) {
//空树
if (root == null) {
return null;
}
Node target = findNode(value);
Node targetParent = findNodeParent(value);
if (target == null) {
return null;
} else {
//找到了待删除节点
//情况1:待删除节点没有左右子树 -> 直接删除
if (target.left == null && target.right == null) {
if (targetParent == null) {
//表示没有子树和父节点,整棵树只有待删除节点一个节点,直接置空
root = null;
return target;
} else {
//有父节点,但有可能是该父节点的左或右子节点
if (targetParent.left == null) {
targetParent.right = null;
return target;
} else {
targetParent.left = null;
return target;
}
}
} else if (target.left == null || target.right == null) {
//情况2:待删除节点有左子树或者右子树 -> 删除待删除节点,将待删除节点的左子树或右子树嫁接到它的父节点
if (target.left == null) {
if (targetParent == null) {
root = target.right;
return target;
}
if (targetParent.left != null && target.left.data == value) {
targetParent.left = target.right;
return target;
} else {
targetParent.right = target.right;
return target;
}
} else {
if (targetParent == null) {
root = target.left;
return target;
}
if (targetParent.left != null && target.left.data == value) {
targetParent.left = target.left;
return target;
} else {
targetParent.right = target.left;
return target;
}
}
} else {
//情况3:待删除节点既有左子树又有右子树 -> 找到中序排序下的前驱或者后驱节点(即是中序排序后,前后节点;这里寻找后节点,即是后驱节点),用它代替待删除节点
Node finalLeft = findFinalLeft(target);
int data = finalLeft.data;
del(data);
target.data = data;
}
}
return null;
}
完整代码
package com.cxf.datastructures.binarytree;
/**
* 排序二叉树
*/
public class BinarySortTree {
public static void main(String[] args) {
BinarySortTree binarySortTree = new BinarySortTree();
binarySortTree.add(3);
binarySortTree.add(1);
binarySortTree.add(6);
binarySortTree.add(5);
binarySortTree.add(2);
binarySortTree.add(9);
binarySortTree.add(7);
System.out.println("删除前: ");
binarySortTree.travel(binarySortTree.root);
binarySortTree.del(6);
System.out.println();
System.out.println("删除后: ");
binarySortTree.travel(binarySortTree.root);
}
private Node root;
/**
* 中序遍历
*
* @param node
*/
private void travel(Node node) {
if (node == null) {
return;
}
travel(node.left);
System.out.print(node.data + " ");
travel(node.right);
}
/**
* 添加节点
*
* @param data
*/
private void add(int data) {
Node newNode = new Node(data);
if (root == null) {
root = newNode;
return;
}
Node current = root;
while (true) {
if (current.data > data) {
if (current.left == null) {
current.left = newNode;
return;
}
current = current.left;
} else {
if (current.right == null) {
current.right = newNode;
return;
}
current = current.right;
}
}
}
/**
* 寻找某个节点
*
* @param value
* @return
*/
private Node findNode(int value) {
Node current = root;
while (true) {
if (current == null) {
return null;
}
if (current.data == value) {
return current;
}
if (current.data > value) {
current = current.left;
} else {
current = current.right;
}
}
}
/**
* 寻找某个节点的父节点
*
* @param value
* @return
*/
private Node findNodeParent(int value) {
if (root == null) {
return null;
}
if (root.data == value) {
return null;
}
Node current = root;
while (true) {
if (current == null) {
return null;
}
if (current.data > value) {
if (current.left == null) {
return null;
}
if (current.left.data == value) {
return current;
}
current = current.left;
} else {
if (current.right == null) {
return null;
}
if (current.right.data == value) {
return current;
}
current = current.right;
}
}
}
/**
* 寻找中序遍历下node节点的后驱节点
* 找到以node为根的树的左边的左边的左边的...的那个节点
*
* @param node
* @return
*/
private Node findFinalLeft(Node node) {
while (node.left != null) {
node = node.left;
}
return node;
}
/**
* 删除某个节点(三种情况)
*
* @param value
* @return
*/
private Node del(int value) {
//空树
if (root == null) {
return null;
}
Node target = findNode(value);
Node targetParent = findNodeParent(value);
if (target == null) {
return null;
} else {
//找到了待删除节点
//情况1:待删除节点没有左右子树 -> 直接删除
if (target.left == null && target.right == null) {
if (targetParent == null) {
//表示没有子树和父节点,整棵树只有待删除节点一个节点,直接置空
root = null;
return target;
} else {
//有父节点,但有可能是该父节点的左或右子节点
if (targetParent.left == null) {
targetParent.right = null;
return target;
} else {
targetParent.left = null;
return target;
}
}
} else if (target.left == null || target.right == null) {
//情况2:待删除节点有左子树或者右子树 -> 删除待删除节点,将待删除节点的左子树或右子树嫁接到它的父节点
if (target.left == null) {
if (targetParent == null) {
root = target.right;
return target;
}
if (targetParent.left != null && target.left.data == value) {
targetParent.left = target.right;
return target;
} else {
targetParent.right = target.right;
return target;
}
} else {
if (targetParent == null) {
root = target.left;
return target;
}
if (targetParent.left != null && target.left.data == value) {
targetParent.left = target.left;
return target;
} else {
targetParent.right = target.left;
return target;
}
}
} else {
//情况3:待删除节点既有左子树又有右子树 -> 找到中序排序下的前驱或者后驱节点(即是中序排序后,前后节点;这里寻找后节点,即是后驱节点),用它代替待删除节点
Node finalLeft = findFinalLeft(target);
int data = finalLeft.data;
del(data);
target.data = data;
}
}
return null;
}
}
class Node {
int data;
Node left;
Node right;
public Node() {
}
public Node(int data) {
this.data = data;
}
}

430

被折叠的 条评论
为什么被折叠?



