目录
首先需要声明:部分图片来自百战尚学堂
想要了解二叉树,首先我们需要知道树性结构的相关用语:
结点:使用树结构存储的元素都称为“结点”
结点的度:某个结点所拥有的子结点
叶子结点:度为0的结点
分支结点:度不为0的结点
孩子:子节点,当前结点的下层直接结点
双亲:父结点,当前结点的上层直接结点
祖先:当前结点的上层的所有直接结点和间接结点
子孙:当前结点的下层的所有直接结点和间接结点
兄弟:同一双亲的结点
二叉树遍历的方式:
大家可以通过图的序号了解二叉树遍历的方式:
前序遍历:根-左-右
中序遍历:左-根-右
后序遍历:左-右-根
层序遍历:从根节点出发,依次访问左右孩子结点,再从左右孩子出发,依次它们的孩子结点,直到节点访问完毕
那么我们今天就来实现一下中序排序的二叉树:
创建节点类:
我们创建一个允许存放Integer类型以及他的子类的二叉树,
首先需要声明的是树的什么最重要?那肯定是根(root)啊,添加元素,获取元素不都得从根开始找到位置然后添加吗?所以我们需要声明一个root节点类,当我们创建并添加节点的时候需要先创建根再对根进行后续的添加或者获取
第二步:根那什么来表示呢?我们就用节点Node来表示,那么节点类的实现我们刚刚看过二叉树的图了,二叉树节点的元素分为:左子树、元素、右子树,所以我们需要有三个成员变量,分别存放左子树、元素以及右子树
第三步:给定构造方法,当我们添加元素的时候就需要创建对象并给元素赋值,那就需要用到构造方法
添加节点:
然后就是实现添加元素的方法了,我们刚刚讲过了,二叉树的根是最重要的,添加元素就需要从根开始添加或者判断,所以我们需要有一个add方法通过root根来添加结点,而root添加结点的代码我们可以提取出来写成方法:addNode()
首先我们来看add()方法,如果此时root为空,就说明二叉树还没有元素,因为根都还没有怎么可能会有叶子、树枝呢?
第一步:所以我们需要判断root是否为空,如果为空创建结点对象并传入元素,那么此时root的左子树和右子树肯定也是空的
第二步:如果root不为空,那么就通过root根结点添加结点并传入元素
然后我们来看addNode()方法,他是有root根结点直接调用的,以此来操作是在根结点的左边还是根结点的右边添加元素
第一步:判断新结点中的元素是否小于当前结点对象,如果小于那么新结点则放到当前结点的左边,那放到左边我们又要判断了,如果当前结点有左子树了那我们又得判断新结点的元素是否小于当前结点的左子树,如果小于又放到当前结点的左子树的左子树上,反之则放到当前结点的左子树的右子树上,如果当前结点的左子树的左子树上又有结点,然后又要判断......
所以我们可以通过递归的方式对添加元素进行循环判断,直到当前结点的左子树为null的时候说明没有左子树了,那么就可以将结点对象放在这里
第二步:如果新结点中的元素大于当前结点对象,那么就放在当前结点的右子树上,如果当前结点的右子树上有结点了,那么我们又得判断新结点的元素是否大于当前结点的右子树,如果大于又放到当前结点的右子树的右子树上,反之则放在左子树上,如果当前结点的右子树的右子树又有结点,有需要判断......
所以我们也可以通过递归的方式对添加元素进行循环判断,直到当前结点的右子树为null的时候说明没有右子树了,那么就可以将结点对象放在这里
public void addNode(Node<E> node){
//如果新结点中的元素小于当前结点,那么新结点则放到当前结点的左边
if (node.element.intValue() < this.element.intValue()) {
//如果当前结点没有左子树
if(this.left == null) this.left = node;
//如果当前结点有左子树
else this.left.addNode(node);
}
//如果新结点中的元素大于当前结点,那么新结点则放到当前结点的右边
else{
//如果当前结点没有右子树
if(this.right == null) this.right = node;
//如果当前结点有右子树
else this.right.addNode(node);
}
}
我们的二叉树是以中序排序的方式存储方式,所以我们需要通过中序遍历二叉树,而这个中序遍历二叉树的方法也是供给root根节点进行调用的
对外我们使用sort()方法,而sort()方法通过root根结点调用middleBinaryTree()方法进行中序遍历
第一步:那么首先我们需要判断根节点是否为空吧?如果根节点为空那还遍历个啥,说明二叉树中还没有元素,直接返回
第二步:如果根节点不为空,通过root根节点调用middleBinaryTree()方法进行中序遍历
我们来看中序遍历的方法:
此方法我们也是通过递归实现的,如果当前结点的左子树不为空时我们找到最左侧的结点,直到找到之后输出元素,
如果我们找到了最左侧的结点是不是把左结点输出出来了,我们来看一个图,此时我们找到最左侧的结点,此时这个结点是最左结点,但他又是根结点,根据中序遍历:左-根-右的方式,虽然他没有左结点那就输出根-右,如果右子树不为空,继续递归,判断右子树的左子树是否为空
这三句话得以意思其实就是,先找到最左侧结点,最左侧结点就说明没有左子树了,那他肯定就是根那么输出,然后找最左侧结点的右结点......
总结:实现二叉树结构最重要的就是root根节点和节点对象,而节点对象就和双向链表一样,二叉树是左子树+元素+右子树,双向链表是直接前驱+元素+直接后继,所以实现二叉树可以先去看看双向链表是如何实现的