一文搞定二叉排序(搜索)树 (2)

二叉排序树是由若干节点(node)构成的,对于node需要这些属性:left,right,和value。其中left和right是左右指针指向左右孩子子树,而value是储存的数据,这里用int 类型。

node类构造为:

class node {//结点 public int value; public node left; public node right; public node() { } public node(int value) { this.value=value; this.left=null; this.right=null; } public node(int value,node l,node r) { this.value=value; this.left=l; this.right=r; } }

既然节点构造好了,那么就需要节点等其他信息构造成树,有了链表构造经验,很容易得知一棵树最主要的还是root根节点。
所以树的构造为:

public class BinarySortTree { node root;//根 public BinarySortTree() {root=null;} public void makeEmpty()//变空 {root=null;} public boolean isEmpty()//查看是否为空 {return root==null;} //各种方法 }

image-20210405120743003

主要方法

既然已经构造好一棵树,那么就需要实现主要的方法,因为二叉排序树中每个节点都能看作一棵树。所以我们创建方法的是时候加上节点参数(方便一些递归调用)

findmax(),findmin()

findmin()找到最小节点:

因为所有节点的最小都是往左插入,所以只需要找到最左侧的返回即可,具体实现可使用递归也可非递归while循环。

findmax()找到最大节点:

因为所有节点大的都是往右面插入,所以只需要找到最右侧的返回即可,实现方法与findmin()方法一致。

代码使用递归函数

public node findmin(node t)//查找最小返回值是node,调用查看结果时需要.value { if(t==null) {return null;} else if(t.left==null) {return t;} else return(findmin(t.left)); } public node findmax(node t)//查找最大 { if(t==null) {return null;} else if(t.right==null) {return t;} else return(findmax(t.right)); }

查找过程

isContains(int x)

这里的意思是查找二叉查找树中是否存在值为x的节点。

在具体实现上,根据二叉排序树左侧更小,右侧更大的性质进行往下查找,如果找到值为x的节点则返回true,如果找不到就返回false,当然实现上可以采用递归或者非递归,我这里使用非递归的方式。

public boolean isContains(int x)//是否存在 { node current=root; if(root==null) {return false;} while(current.value!=x&&current!=null) { if(x<current.value) {current=current.left;} if(x>current.value) {current=current.right;} if(current==null) {return false;}//在里面判断如果超直接返回 } //如果在这个位置判断是否为空会导致current.value不存在报错 if(current.value==x) {return true;} return false; } insert(int x)

插入的思想和前面isContains(int x)类似,找到自己的位置(空位置)插入。

但是具体实现上有需要注意的地方,我们要到待插入位置上一层节点,你可能会疑问为什么不直接找到最后一个空,然后将current赋值过去current=new node(x),这样的化current就相当于指向一个new node(x)节点,和原来树就脱离关系(原树相当于没有任何操作),所以要提前通过父节点判定是否为空找到位置,找到合适位置通过父节点的left或者right节点指向新创建的节点才能完成插入的操作。

public node insert(int x)// 插入 t是root的引用 { node current = root; if (root == null) { root = new node(x); return root; } while (current != null) { if (x < current.value) { if (current.left == null) { return current.left = new node(x);} else current = current.left;} else if (x > current.value) { if (current.right == null) { return current.right = new node(x);} else current = current.right; } } return current;//其中用不到 }

比如说上面树插入值为51的节点。

插入值为51的节点

delete(int x)

删除操作算是一个相对较难理解的操作了,因为待删除的点可能在不同位置所以具体处理的方式也不同,如果是叶子即可可直接删除,有一个孩子节点用子节点替换即可,有两个子节点的就要先找到值距离待删除节点最近的点(左子树最大点或者右子树最小点),将值替换掉然后递归操作在子树中删除已经替换的节点,当然没具体分析可以看下面:

删除的节点没有子孙:

这种情况不需要考虑,直接删除即可(节点=null即可)(图中红色点均满足这种方式)。

待删除节点为叶子节点

一个子节点为空:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wspxxd.html