一、概念
二叉查找树的特点是每个节点的左子树上的节点都小于该节点,右子树上的节点都大于该节点。
二、常见算法:
1.实现二叉查找树,并且支持插入,删除,查找操作
数据结构:
public class TreeNode {
public int val;
public TreeNode left = null;
public TreeNode right = null;
public TreeNode(){}
public TreeNode(int val){
this.val = val;
}
}
插入:
//创建二叉树,即插入
public TreeNode createTree(int data){
TreeNode newNode = new TreeNode(data);
if(root == null){
root = newNode;
return root;
}
TreeNode current = root;
TreeNode p = null;
while(current != null){
p = current;
if(current.val > data){
current = current.left;
if(current == null){
p.left = newNode;
return root;
}
}
else
{
current = current.right;
if(current == null){
p.right = newNode;
return root;
}
}
}
return root;
}
删除:需要考虑到删除节点的子节点情况
//删除
public void delete(int data){
TreeNode p = root;
TreeNode pp = null;//指向 p 的父节点
// 找到要删除节点的位置
while(p.val != data && p != null){
pp = p;
if(p.val > data) p = p.left;
else p = p.right;
}
//如果没有找到删除的节点,返回空节点
if(p == null) return;
//如果要删除的节点同时存在左节点和右节点
if(p.left != null && p.right != null){
//为了维持二叉查找树的结构,找到右子树最左的节点
TreeNode minp = p.right;
TreeNode minpp = p;
while(minp.left != null){
minpp = minp;
minp = minp.left;
}
p.val = minp.val;
// 联系后面的代码看就知道如何删除了!
p = minp;
pp = minpp;
}
// 删除的节点是叶子节点,或者只有一个叶子节点
//记录要删除节点的位置
TreeNode child ;
if(p.left != null) child = p.left;
else if(p.right != null) child = p.right;
else child = null;
//统一删除
if(pp == null) root = child; // 删除的是根节点
else if(pp.left == p) pp.left = child;
else pp.right = child;
}
查找:
//查找
public void findInTree(int data){
if(root == null)return;
TreeNode p = root;
while(p != null){
if(p.val == data){
System.out.println("找到了!");
return;
}
else if(p.val > data){
p = p.left;
}
else{
p = p.right;
}
}
}
2.实现查找二叉树中某个节点后继节点、前驱节点
后继节点:该节点右子树最小的节点
前驱结点:该节点左子树最大的节点
// 查找某个节点的前驱节点,左子树的最大节点
public TreeNode findMax(int data){
if(root == null) return null;
TreeNode p = root;
//找到该节点
while(p != null){
if(p.val == data){
break;
}
else if(p.val > data){
p = p.left;
}
else{
p = p.right;
}
}
//如果该节点的左子树为空,返回空
if(p.left != null) p = p.left;
else return null;
//查找该节点左子树的最大值
while(p.right != null){
p = p.right;
}
return p;
}
// 查找某个节点的后继节点,右子树的最小节点
public TreeNode findMin(int data){
if(root == null) return null;
TreeNode p = root;
while(p.val != data && p != null){
if(p.val == data) break;
else if (p.val < data) p = p.right;
else p = p.left;
}
if(p.right != null)p = p.right;
else return null;
while(p.left != null){
p = p.left;
}
return p;
}
3.实现二叉树的前,中,后序以及按层遍历
前,中,后序遍历:运用递归的思想
//前序遍历
public void preOrder(TreeNode root){
if(root != null){
System.out.print(root.val + " ");
preOrder(root.left);
preOrder(root.right);
}
}
//中序遍历
public void midOrder(TreeNode root){
if(root != null){
midOrder(root.left);
System.out.print(root.val + " ");
midOrder(root.right);
}
}
//后序遍历
public void lastOrder(TreeNode root){
if(root != null){
lastOrder(root.left);
lastOrder(root.right);
System.out.print(root.val + " ");
}
}
按层遍历:借助队列实现
//按层遍历
public void breadthOrder(TreeNode root){
if(root == null) return;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
TreeNode temp = queue.poll();
System.out.print(temp.val + " ");
if(temp.left != null)
queue.add(temp.left);
if(temp.right != null)
queue.add(temp.right);
}
}
}