二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值 它的左右子树也分别为二叉搜索树



设待删除结点为 cur, 待删除结点的双亲结点为 parent 一、cur.left == null
二、 cur.right == null
三、. cur.left != null && cur.right != null 需要使用替换法进行删除,即在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题
import com.sun.source.tree.Tree;
public class BinarySearchTree {
static class TreeNode{
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
public TreeNode root;
public void insert(int val){
if(root == null){
root = new TreeNode(val);
return;
}
TreeNode node = new TreeNode(val);
TreeNode cur = root;
TreeNode parent = null;
while(cur != null){
if(node.val > cur.val){
parent = cur;
cur = cur.right;
}else if(node.val < cur.val){
parent = cur;
cur = cur.right;
}else{
return;
}
}
if(parent.val < node.val){
parent.right = node;
}else{
parent.left = node;
}
}
public TreeNode search(int val){
TreeNode cur = root;
while(cur != null){
if(cur.val < val){
cur = cur.right;
} else if (cur.val > val) {
cur = cur.left;
}else{
return cur;
}
}
return null;
}
public void remove(int key){
TreeNode cur = root;
TreeNode parent = root;
while(cur.val != key){
if(cur.val < key){
parent = cur;
cur = cur.right;
}else{
parent = cur;
cur = cur.left;
}
}
if(cur.left == null){
if(cur == root){
root = root.right;
}else if(cur.val < parent.val){
parent.left = cur.right;
}else{
parent.right = cur.right;
}
} else if (cur.right == null) {
if(cur == root){
root = root.left;
} else if (cur.val < parent.val) {
parent.left = cur.left;
}else{
parent.right = cur.left;
}
}else{
removeCur(cur,parent);
}
}
private void removeCur(TreeNode target, TreeNode parent) {
TreeNode tp = target;
parent = target;
target = target.right;
while(target.left!= null){
parent = target;
target = target.left;
}
tp.val = target.val;
if(parent.left == target){
parent.left = target.right;
}else{
parent.right = target.right;
}
}
}这里我的删除采用的是找到右子树最小值替换。
插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。 对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。 但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:

最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:logN 最差情况下,二叉搜索树退化为单支树,其平均比较次数为:N/2 问题:如果退化成单支树,二叉搜索树的性能就失去了。那能否进行改进,不论按照什么次序插入关键码,都可以是二叉搜索树的性能最佳?
Map和set是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关。以前常见的搜索方式有:
上述排序比较适合静态类型的查找,即一般不会对区间进行插入和删除操作了,而现实中的查找比如:
可能在查找时进行一些插入和删除的操作,即动态查找,那上述两种方式就不太适合了,本节介绍的Map和Set是一种适合动态查找的集合容器。
一般把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称之为Key-value的键值对,所以模型会有两种:

Map是一个接口类,该类没有继承自Collection,该类中存储的是<K,V>结构的键值对,并且K一定是唯一的,不能重复。
Map.Entry<K, V> 是Map内部实现的用来存放<key, value>键值对映射关系的内部类(接口类),该内部类中主要提供了<key, value>的获取,value的设置以及Key的比较方式。 所以后面的TreeMap实现了Map接口的同时也需要实现这个内部类。
K getKey() : 返回 entry 中的 key
V getValue() : 返回 entry 中的 value
V setValue(V value) : 将键值对中的value替换为指定value

注意:

public static void main(String[] args) {
Map<String,Integer> map = new TreeMap<>();
map.put("hello",5);
map.put("world",7);
System.out.println(map.get("hello"));
System.out.println(map.get("a"));
System.out.println(map.getOrDefault("a",8));
//int a = map.get("a");
Integer A = map.get("a");
System.out.println(A);
Set<String> set = map.keySet();
System.out.println(set);
for(Map.Entry<String,Integer> s: map.entrySet()){
System.out.println("key: "+s.getKey() +" val: "+s.getValue());
}
}
Set与Map主要的不同有两点:Set是继承自Collection的接口类,Set中只存储了Key。

注意:
与TreeMap类似的就不重新演示了
public static void main(String[] args) {
Set<Integer> treeSet = new TreeSet<>();
treeSet.add(1);
treeSet.add(9);
treeSet.add(5);
treeSet.add(3);
System.out.println(Arrays.toString(treeSet.toArray()));
Iterator<Integer> it = treeSet.iterator();
while(it.hasNext()){
System.out.print(it.next() + " ");
}
System.out.println();
}