前面介绍学习的大可能是线性表相关的内容,把指针搞懂后其实也没有什么难度。规则相对是简单的。java
再数据结构中树
、图
才是数据结构标志性产物,(线性表大多都现成api可使用),由于树的难度相比线性表大一些
而且树的拓展性很强
,你所知道的树、二叉树、二叉排序树,AVL树,线索二叉树、红黑树、B数、线段树等等高级数据结构。然而二叉排序树是全部的基础,因此完全搞懂二叉排序树也是很是重要的。node
参考王道数据结构算法
二叉树也是树的一种,而二叉排序树又是二叉树的一种。后端
递归
的,将树的任何一个节点以及节点下的节点都能组合成一个新的树
。而且不少操做基于递归完成。没有前驱节点
,只有子节点(0个或多个均可以)第1层
(有的也说第0层)。而树的高度就是层数最高(上图层数开始为1)节点的层数父节点
:就是连接该节点的上一层节点,孩子节点:
和父节点对应,上下关系。而祖先节点
是父节点的父节点(或者祖先)节点。兄弟节点:
拥有同一个父节点的节点们!孩子节点
的个数(是孩子不是子孙).而树的度(最大)节点的度。同时,若是度大于0就成为分支节点
,度等于0就成为叶子节点
(没有子孙)。相关性质:api
等比数列求和
)二叉树是一树的一种,但应用比较多,因此须要深刻学习。二叉树的每一个节点最多只有两个节点
。数据结构
二叉树与度为2的树的区别:函数
几种特殊二叉树:学习
二叉树性质:
相比树,二叉树的性质就是树的性质更加具体化。this
度为2的节点树+1
.原本一个节点若是度为1.那么一直延续就一个叶子,但若是出现一个度为2除了延续原来的一个节点,会多出一个节点须要维系。因此到最后会多出一个叶子
。彻底二叉树
若从左往右,从上到下编号如图:前面铺垫那么多,我们言归正传
,详细实现一个二叉排序树。首先要了解二叉排序树的规则:spa
15,6,23,7,4,71,5,50
会造成下图顺序首先二叉排序树是由若干节点
构成。
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;} //各类方法 }
节点参数
(也就是函数对每个节点都能有效
)findmin()找到最小节点:
findmax()找到最大节点:
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)); }
这里的意思是查找二叉查找树中是否存在x。
路径的过程当中遇到x
。由于你能够若是已经存在的点,再它的前方会走一次和它相同的步骤。也就是说前面固定,我来1w次x,那么x都会到达这个位置
。那么咱们直接进行查找比较便可!public boolean isContains(int x)//是否存在 { node current=root; if(root==null) {return false;} while(current.value!=x&¤t!=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; }
插入的思想和前面isContains
相似。找到本身的位置(空位置)插入。可是又不太同样。你可能会疑问为何不直接找到最后一个空,而后将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
删除操做算是一个相对较难理解的操做了。
删除节点规则:
分类讨论
,若是有两个儿子,就选右边儿子的最左侧那个点替代
,而后再子树删除替代的那个点
。若是是一个节点,判断是左空仍是右空,将这个点指向不空的那个
。不空的那个就替代了这个节点。入股左右都是空,那么他本身变空null就删除了。删除的节点没有子孙:
节点=null
便可。左节点为空、右节点为空:
删除点的子节点放到被删除位置
便可。左右节点均不空
涉及
到一个策略问题。19或者71
节点填补。虽然能够保证部分侧大于小于该节点,可是会引发合并的混乱
.好比你若用71替代23节点。那么你须要考虑三个节点(19,50,75)
之间如何处理,还要考虑他们是否满,是否有子女。这是个极其复杂的过程。选一个最大的点
让左半枝都比它小。咱们分析左支最大的点
必定是子树最右侧
!直接替换值,而后将最底层的点删除
便可。可是若是
这个节点有左枝
。咱们该怎么办?知足的节点替换
了。会产生什么样的后果?19
的点!那么这个问题又转化为删除节点的问题,查找左子树中有没有可以替代19
这个点的。因此整个删除算法流程为:
代码为
public node remove(int x, node t)// 删除节点 { if (t == null) { return null; } if (x < t.value) { t.left = remove(x, t.left); } else if (x > t.value) { t.right = remove(x, t.right); } else if (t.left != null && t.right != null)// 左右节点均不空 { t.value = findmin(t.right).value;// 找到右侧最小值替代 t.right = remove(t.value, t.right); } else // 左右单空或者左右都空 { if (t.left == null && t.right == null) { t = null; } else if (t.right != null) { t = t.right; } else if (t.left != null) { t = t.left; } return t; } return t; }
二叉排序树完整代码为:
package 二叉树; import java.util.ArrayDeque; import java.util.Queue; import java.util.Stack; public class BinarySortTree { 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; } } node root;// 根 public BinarySortTree() { root = null; } public void makeEmpty()// 变空 { root = null; } public boolean isEmpty()// 查看是否为空 { return root == null; } 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)); } 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; }