Data structure ------ Binary sort tree

Binary Sort Tree

First look at a demand

Give you a number sequence (7,3, 10, 12,5,1,9), which requires the ability to query and add data efficiently.

We generally think of arrays first

The array is not sorted. Advantages : add directly at the end of the array, which is fast. Disadvantages : slow search speed.
Array sorting. Advantages : binary search can be used. The search speed is fast. Disadvantages : In order to ensure the order of the array, when adding new data, after finding the insertion position, the following data needs to be moved as a whole, which is slow.

What about chained storage?

Regardless of whether the linked list is ordered or not, the search speed is slow, and the speed of adding data is faster than that of the array, and there is no need to
move the data as a whole .

We mentioned earlier that tree storage can be effectively solved. Why on earth?

Binary Sort Tree

Introduction

Binary sort tree: BST: (Binary Sort (Search ) Tree), for any non-leaf node binary sort tree,
requires the value of the left child node is less than the value of the current node , the value of right child than the current node Great value .
Special note: If there are the same values, the node can be placed in the left child node or the right child node

The creation and traversal of binary sort tree

package 二叉排序树;

public class BinarySortTree {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		int[] arr= {
    
    7,3,10,12,5,1,9};
		BinarySortTreeDemo binarySortTree = new BinarySortTreeDemo();
		//循环添加节点到二叉树
		for (int i = 0; i < arr.length; i++) {
    
    
			binarySortTree.addNode(new Node(arr[i]));
		}
//		System.out.println("中序遍历二叉树");
		binarySortTree.infixOrder();
	}

}
//创建二叉排序树
class BinarySortTreeDemo{
    
    
	private Node root;
	//添加节点的方法
	public void addNode(Node node){
    
    
		if(root == null){
    
    
			root = node;
		}else{
    
    
			root.addNode(node);
		}
	}
	//中序遍历
	public void infixOrder(){
    
    
		if(root != null){
    
    
			root.infixOrder();
		}else{
    
    
			System.out.println("空树");
		}
	}
}
class Node{
    
    
	int value;
	Node left;
	Node right;
	public Node(int value) {
    
    
		super();
		this.value = value;
	}
	
	@Override
	public String toString() {
    
    
		return "Node [value=" + value + "]";
	}

	//添加节点的方法
	//递归的形式添加节点,需要满足二叉排序树
	public void addNode(Node node){
    
    
		if(node == null){
    
    
			return;
		}
		//判断传入的节点值,跟当前子树根节点值的关系
		if(node.value < this.value){
    
    
			//如果当前节点的左子节点为空
			if(this.left == null){
    
    
				this.left = node;
			}else
			{
    
    
				this.left.addNode(node);//递归添加
			}
		}else{
    
    
			if(this.right == null){
    
    
				this.right = node;
			}else{
    
    
				this.right.addNode(node);
			}
		}
	}
	//中序遍历
	public void infixOrder(){
    
    
		if(this.left != null){
    
    
			this.left.infixOrder();
		}
		System.out.println(this);
		if(this.right != null){
    
    
			this.right.infixOrder();
		}
	}
}

Deletion of Binary Sort Tree

There are many situations in this:

1. Delete the leaf node

2. Delete the node with only one subtree

3. Delete the node with two subtrees

Ideas

Case 1: Delete the leaf node

1. You need to find the targetNode to be deleted first

2. Find the parent node of the node to be deleted (consider whether there is a parent node)

3. Determine whether targetNode is the left child node or the right child node of parent

4. According to the previous, delete the corresponding

Case 2: Delete a node with only one subtree

1. You need to find the targetNode to be deleted first

2. Find the parent node of the node to be deleted (consider whether there is a parent node)

3. Determine whether the child node of targetNode is the left child node or the right child node

4. Determine whether targetNode is the left child node or the right child node of parent

5. If targetNode has a left child node

1) targetNode is the left child node of parent

parent.left = targetNode = left;

2) targetNode is the right child node of parent

parent.left = targetNode .right;

6. The same is true if targetNode has a right child node

Case 3: Delete a node with two subtrees

1. You need to find the targetNode to be deleted first

2. Find the parent node of the node to be deleted (consider whether there is a parent node)

3. Find the smallest node from the right subtree of targetNode

4. Use temporary variables to save the value of the smallest node temp

5. Delete the smallest node

6.targetNode.value = temp

Delete node code

package 二叉排序树;

public class BinarySortTree {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		int[] arr= {
    
    7,3,10,12,5,1,9,2};
		BinarySortTreeDemo binarySortTree = new BinarySortTreeDemo();
		//循环添加节点到二叉树
		for (int i = 0; i < arr.length; i++) {
    
    
			binarySortTree.addNode(new Node(arr[i]));
		}
//		System.out.println("中序遍历二叉树");
		binarySortTree.infixOrder();
		
		//测试删除叶子节点
//		binarySortTree.delNode(2);
//		System.out.println("删除2节点后");
//		binarySortTree.infixOrder();
		binarySortTree.delNode(10);
		binarySortTree.infixOrder();

	}

}
//创建二叉排序树
class BinarySortTreeDemo{
    
    
	private Node root;
	//添加节点的方法
	public void addNode(Node node){
    
    
		if(root == null){
    
    
			root = node;
		}else{
    
    
			root.addNode(node);
		}
	}
	//中序遍历
	public void infixOrder(){
    
    
		if(root != null){
    
    
			root.infixOrder();
		}else{
    
    
			System.out.println("空树");
		}
	}
	//查找要删除的节点
	public Node search(int value){
    
    
		if(root == null){
    
    
			return null;
		}else{
    
    
			return root.search(value);
		}
	}
	//查找待删除节点的父节点
	public Node searchParent(int value){
    
    
		if(root == null){
    
    
			return null;
		}else{
    
    
			return root.searchParent(value);
		}
	}
	//编写方法
	/**
	 * 返回最小节点值,并且删除以node为根节点的二叉排序树的最小节点
	 * @param node	当做一颗二叉排序树的根节点
	 * @return		返回的以node为根节点的二叉排序树的最小节点的值
	 */
	public int delRightTreeMin(Node node){
    
    
		Node target = node;
		//循环查找左子节点,就会找到最小值
		while(target.left != null){
    
    
			target = target.left;
		}
		//这是target就指向了最小节点
		//删除最小节点
		delNode(target.value);
		return target.value;
	}
	
	//删除叶子结点的方法
	public void delNode(int value){
    
    
		if(root == null){
    
    
			return;
		}else{
    
    
			//1.需要先去找到待删除节点
			Node targetNode = search(value);
			//如果没有找到
			if(targetNode == null){
    
    
				return;
			}
			//如果当前这课二叉排序树只有一个节点
			if(root.left == null&& root.right == null){
    
    
				root = null;
				return;
			}
			//去查找targetNode的父节点
			Node parent = searchParent(value);
			//如果待删除的节点是叶子结点
			if(targetNode.left == null && targetNode.right == null){
    
    
				//如果targetNode是parent的左子节点
				if(parent.left != null && parent.left.value == targetNode.value){
    
    
					parent.left = null;
				}else if(parent.right != null && parent.right.value == targetNode.value){
    
    
					parent.right = null;
				}
			}else if(targetNode.left!=null && targetNode.right != null){
    
    
				int minValue = delRightTreeMin(targetNode.right);
				targetNode.value = minValue;
			}else{
    
    
				//删除只有一个子树的节点
				//如果删除的节点有左子节点
				if(targetNode.left != null){
    
    
					if(parent.left.value == targetNode.value){
    
    
						parent.left = targetNode.left;
					}else{
    
    
						parent.right = targetNode.left;
					}
				}else{
    
    
					//要删除的节点有右子节点
					if(parent.left.value == targetNode.value){
    
    
						parent.left = targetNode.right;
					}else{
    
    
						parent.right = targetNode.right;
					}
				}
			}
		}
	}
}
class Node{
    
    
	int value;
	Node left;
	Node right;
	public Node(int value) {
    
    
		super();
		this.value = value;
	}
	
	@Override
	public String toString() {
    
    
		return "Node [value=" + value + "]";
	}

	/**
	 * 查找待删除的节点
	 * @param value	待删除节点的值
	 * @return
	 */
	public Node search(int value){
    
    
		if(value == this.value){
    
    
			return this;
		}else if(value < this.value){
    
    //应该向左子树递归查找
			if(this.left != null){
    
    
				return this.left.search(value);
			}else{
    
    
				return null;
			}
		}else{
    
    
			if(this.right == null){
    
    
				return null;
			}else{
    
    
				return this.right.search(value);
			}
		}
	}
	/**
	 * 查找待删除节点的父节点
	 * @param value		待删除节点的值
	 * @return     返回待删除节点的父节点
	 */
	public Node searchParent(int value){
    
    
		if((this.left !=null && this.left.value == value) || (this.right != null && this.right.value == value)){
    
    
			//当前节点就是待删除节点的父节点
			return this;
		}else{
    
    
			//如果查找的值,小于当前节点的值,且当前节点的左子节点不为空
			if(value < this.value && this.left != null){
    
    
				return this.left.searchParent(value);
			}else if(value >= this.value && this.right != null){
    
    
				return this.right.searchParent(value);
			}else{
    
    
				return null;//没有找到父节点
			}
		}
	}
	
	
	//添加节点的方法
	//递归的形式添加节点,需要满足二叉排序树
	public void addNode(Node node){
    
    
		if(node == null){
    
    
			return;
		}
		//判断传入的节点值,跟当前子树根节点值的关系
		if(node.value < this.value){
    
    
			//如果当前节点的左子节点为空
			if(this.left == null){
    
    
				this.left = node;
			}else
			{
    
    
				this.left.addNode(node);//递归添加
			}
		}else{
    
    
			if(this.right == null){
    
    
				this.right = node;
			}else{
    
    
				this.right.addNode(node);
			}
		}
	}
	//中序遍历
	public void infixOrder(){
    
    
		if(this.left != null){
    
    
			this.left.infixOrder();
		}
		System.out.println(this);
		if(this.right != null){
    
    
			this.right.infixOrder();
		}
	}
}

Precautions

When deleting multiple nodes, you must pay attention to the order. Some orders can be deleted normally, but some orders will report a null pointer error. The reason is that there is a problem with the order of deletion, which leads to a problem with the judgment in our deletion method, which is the root node. In this place, he has no parent node, but we judged it, so there is an error here

Guess you like

Origin blog.csdn.net/qq_22155255/article/details/113825468