1、二叉搜索树
二叉搜索树(Binary Search Tree),又叫二叉排序树/二叉查找树。
它的每个左子树都比根小,右子树都比根大。
并且中序遍历是一个有序的序列。
二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势,所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。
如图:
对它进行中序遍历是一个递增的序列
2、插入的实现
1、如果是空树,直接将root指向这个结点
2、定义parent每次表示cur的父结点
3、要想知道cur是走到了左边还是右边,需要把key和parent.data比较。
static class Node {
public int data;
public Node left;
public Node right;
public Node(int data) {
this.data = data;
}
}
public boolean insert(int key) {
Node node = new Node(key);
if(root == null) {
root = node;
return true;
}
Node parent = null;
Node cur = root;
while (cur != null) {
if(cur.data == key) {
return false;
}else if(cur.data < key) {
parent = cur;
cur = cur.right;
}else {
parent = cur;
cur = cur.left;
}
}
//cur == null
if(key < parent.data) {
parent.left = node;
}else {
parent.right = node;
}
return true;
}
3、查找的实现
public Node search(int val) {
Node cur = root;
while (cur != null) {
if(cur.data == val) {
return cur;
}else if(cur.data < val) {
cur = cur.right;
}else {
cur = cur.left;
}
}
return null;
}
4、删除的实现
设待删除结点为cur,待删除结点的双亲结点为parent
第一种情况:cur.left==null
1、cur是root,则root=cur.right
2、cur不是root,cur是parent.left,则parent.left=cur.right
3、cur不是root,cur是parent.right ,则parent.right=cur.right
第二种情况:cur.right=null
1、cur是root,则root=cur.left
2、cur不是root,cur是parent.left,则parent.left=cur.left
3、cur不是root,cur是parent.right,则parent.right=cur.left
3、cur.left!=null && cur.light!=null
需要使用替换法进行删除,即在它的右子树中寻找中序下的第一个结点, 用它的值填补到被删除结点中,再来处理该结点的删除问题。
public void remove(int key) {
Node parent = null;
Node cur = root;
while (cur != null) {
if(cur.data == key) {
removeNode(parent,cur);
return;
}else if(cur.data < key) {
parent = cur;
cur = cur.right;
}else {
parent = cur;
cur = cur.left;
}
}
}
private void removeNode(Node parent,Node cur) {
if(cur.left == null) {
//3种情况
if(cur == root) {
root = cur.right;
}else if(cur == parent.left) {
parent.left = cur.right;
}else {
parent.right = cur.right;
}
}else if(cur.right == null) {
if(cur == root) {
root = cur.left;
}else if(cur == parent.left) {
parent.left = cur.left;
}else {
parent.right = cur.left;
}
}else {
Node targetParent = cur;
Node target = cur.right;//替罪羊
while (target.left != null) {
targetParent = target;
target = target.left;
}
//并没有删除 只是一个简单的值的偷换
cur.data = target.data;
//分为两种情况:
//1、因为是在右边找,找的是右边最小的数字,又因为右边最小的数字 肯定是左树为空
//2、所以 删除的时候 分为两种情况
if(target == targetParent.left) {
targetParent.left = target.right;
}else {
targetParent.right = target.right;
}
}
}