二叉搜索树
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
二叉搜索树操作
- 因为二叉树搜索树的特点,我们插入一个元素必然需要从根节点开始查找整个树,直到找到准确的位置
- 二叉搜索树查询很快logn
- 二叉搜索树的删除
- 如果要删除的节点是叶子节点 直接删除,父节点对应子树设为null
- 如果要删除的节点只有一个子树,父节点指向当前节点的子树。
- 如果要删除的节点有2个子树,则先找到当前节点的后继节点,把后继节点的值赋值给当前节点。删除后继节点,因为后继节点肯定不会有2个子树。
代码再现
public class MyBinarySeachTree {
private TreeNode root;
static class TreeNode {
private TreeNode left;//左节点
private TreeNode right;//右节点
private TreeNode parent;//父节点
private int data;//数据值
private boolean position = false;//表示左边
public TreeNode(int data) {
this.data = data;
}
}
public MyBinarySeachTree(int data) {
root = new TreeNode(data);
}
/**
* 正常插入法
* @param data
*/
public void insert(int data) {
TreeNode node = new TreeNode(data);
TreeNode pa = root.right;
if( node.data >= root.data) {
pa = root.right;
}else{
pa = root.left;
}
while( true ) {
if( pa == null && node.data >= root.data ) {
root.right = node;
node.parent = root;
node.position = true;
break;
}else if(pa == null && node.data < root.data) {
root.left = node;
node.parent = root;
break;
}
if( node.data >= pa.data){
if( pa.right != null) {
pa = pa.right;
continue;
}
pa.right = node;
node.parent = pa;
node.position = true;
break;
}else if(node.data < pa.data ){
if( pa.left != null) {
pa = pa.left;
continue;
}
pa.left = node;
node.parent = pa;
break;
}
}
}
/**
* 递归插入法
* @param root
* @param data
*/
public void insert(TreeNode root , int data) {
if( data > root.data) {
if(root.right ==null) {
TreeNode node = new TreeNode(data);
root.right = node;
node.parent = root;
node.position = true;
return;
}
insert(root.right, data);
}else {
if(root.left ==null) {
TreeNode node = new TreeNode(data);
root.left = node;
node.parent = root;
return;
}
insert(root.left, data);
}
}
public TreeNode search(TreeNode root , int data) {
if(root == null) {
System.out.println("没有找到");
return null;
}
if( data > root.data) {
return search(root.right, data);
}else if(data < root.data ) {
return search(root.left, data);
}else{
System.out.println("找到节点了");
return root;
}
}
private TreeNode findNextNode(TreeNode node) {
TreeNode parent = node;
while(parent.left != null) {
parent = parent.left;
}
return parent;
}
/**
* 9
* 7 11
* 5 8 10 16(X)
*2 6 12 24
* 19 26
* 20 28
*
* 1.要删除的结点是叶子结点 O(1)
* 2.要删除的结点只有一个子树(左或者右)O(1)
* 3.要删除的结点有两颗子树:找后继结点,而且后继结点的左子树一定为空。
*
*
* @param data
*/
public void remove(int data) {
TreeNode node = search(root, data);
remove(node);
}
private void remove(TreeNode node) {
if( node !=null ) {
//先判断是否存在左右子树
if(node.left ==null || node.right == null) {
if(node.left != null && node.position==false) node.parent.left = node.left;//要删除节点的左子树不为空,并且当前节点是父节点的左子树
else if(node.left != null && node.position==true) node.parent.right = node.left;//要删除节点的左子树不为空,并且当前节点是父节点的右子树
else if(node.right != null && node.position==false) node.parent.left = node.right;//要删除节点的右子树不为空,并且当前节点是父节点的左子树
else if(node.right != null && node.position==true) node.parent.right = node.right;//要删除节点的右子树不为空,并且当前节点是父节点的右子树
else if(node.position==false) node.parent.left = null; //当前节点是父节点的左子树
else node.parent.right = null; //当前节点是父节点的右子树
//移除当前节点
node = null;
}else{//查找当前节点的后继节点
TreeNode treeNode = findNextNode(node.right);
node.data = treeNode.data;
remove(treeNode);
}
}
}
public void print() {
show(root);
System.out.println("");
}
private void show(TreeNode node) {
if(node == null) {
return;
}
show(node.left);
System.out.print(node.data+ " ");
show(node.right);
}
public static void main(String[] args) {
int data[] = {9,7,11,5,8,10,16,2,6,12,24,19,26,20,28};
MyBinarySeachTree root = new MyBinarySeachTree(data[0]); //第一个点作为跟结点
for(int i = 1 ; i < data.length ; i ++) {
//root.insert(root, data[i]);
root.insert(data[i]);
}
root.print();
root.remove(16);
System.out.println("删除节点:"+16);
root.print();
}
}