前言前面介绍的大部分学习都是和线性表相关的。理解了指针之后,就不难了。规则比较简单,后面会讲解一些比较通用的数据结构,以多图的方式让大家更容易吸收。在数据结构和算法中,树是一个比较大的家族。家族中有很多有权势的成员。这些成员包括二叉树和多叉树(如B+树等),而在二叉树这个大家族中,二叉搜索树(也称为二叉排序树)是最基本的,在此基础上可以继续拓展学习AVL(二叉平衡树)、红黑树等知识。对于二叉排序树,本章重点介绍它的实现和插入、删除的步骤。我们会手写一个二叉排序树,二叉树遍历部分的内容会单独详细讲解。什么是树?树是一种数据结构,它是由n(n>=1)个有限节点组成的一组层次关系。它被称为“树”,因为它看起来像一棵倒置的树,这意味着它的根朝上,叶子朝下。树是递归的,树的任意一个节点和该节点下的节点都可以组合成一棵新树,所以树的很多问题都是用递归解决的。根节点:最顶层节点(root),根节点没有父节点,只有子节点(0个或多个都可以)层数:一般认为根节点是第一层(也有的说是第0层),树的高度为层数最高的节点的层数(上层数从1开始)节点关系:父节点:与该节点相连的上层节点,子节点:对应到父节点,上下关系。祖先节点是父节点的父节点(或祖先)节点。兄弟节点:父节点相同的节点!节点度:该节点拥有的子节点数(直连子节点,不是后代)。树度:所有节点中最大的(节点的度)。同时,如果度数大于0的节点是分支节点,则度数等于0的节点是叶子节点(没有后代)。相关性质:二叉树二叉树是树的一种,但是应用较多,需要深入研究。二叉树的每个节点最多有两个子节点(但不一定是两个节点)。二叉树和度数为2的树的区别:1.度数为2的树必须有3个以上节点(否则不叫度数为2的,必须先存在),而二叉树树可以是空的。2、二叉树的度不一定是2,比如斜树。3、二叉树有左右节点之分,而度数为2的树没有左右节点之分。几种特殊的二叉树:满二叉树:一棵高度为n的满二叉树有(2^n)-1个节点fullbinarytree完全二叉树:上层全是满二叉树,底层依次从上到下排列从左到右完全二叉树二叉排序树:按照一定的规则插入树并排序(本文有详细介绍)。平衡二叉树:树上任意节点的左子树和右子树的深度差不超过1(后面详述)。二叉树的性质:1.二叉树的有用树的性质。2、非空二叉树的叶子节点个数=度数为2+1的节点个数。本来一个节点如果度数为1,它会继续做叶子,但是如果有度数为2的节点,除了继续原来的节点,还会多出一个节点需要维护.所以最后会有一片额外的叶子。3.非空第i层最多有2^(i-1)个节点。4.一棵高度为h的树,至多有(2^h)-1个节点(等比求和)。二叉树一般都是链式存储,这样内存利用率比较高,但是二叉树也可以用数组存储(经常遇到),计算每个节点对应的下标。如果从左到右取一棵完整的二叉树,从上到下编号如图:一棵二叉排序树的详细介绍,二叉查找树具有二叉树的性质,同时有其自身的一些规则:首先,你必须了解二叉排序树的规则:从任意一个节点开始,节点左侧的节点值总是小于节点右侧的值。例如,将15、6、23、7、4、71、5、50依次插入二叉排序树中,就会形成下图所示的序列。构建了一个二叉排序树。二叉排序树由多个节点组成。对于节点,这些属性是必需的:left、right和value。其中left和right是指向左右子树的左右指针,value是存储的数据,这里使用int类型。节点类构造为:classnode{//nodepublicintvalue;publicnodeleft;publicnoderight;publicnode(){}publicnode(intvalue){this.value=value;this.left=null;this.right=null;}publicnode(intvalue,nodel,noder){this.value=value;this.left=l;this.right=r;}}既然已经构造了节点,接下来就要用节点等其他信息构造一棵树。有了构造链表的经验,很容易知道一棵树最重要的是根节点。所以树的结构是:publicclassBinarySortTree{noderoot;//rootpublicBinarySortTree(){root=null;}publicvoidmakeEmpty()//清空{root=null;}publicbooleanisEmpty()//检查是否为空{returnroot==空;}//各种方法}可以用一个图来表示这个结构:既然main方法已经构造了一棵树,那么就需要实现main方法,因为二叉排序树中的每个节点都可以看作是一棵树。所以我们在创建方法的时候,是时候加入节点参数了(方便一些递归调用)findmax(),findmin()findmin()寻找最小的节点:因为所有节点中最小的插入到左边,所以只需要找到最左边的返回即可,具体实现可以使用递归或者非递归while循环。findmax()寻找最大节点:因为所有较大的节点都向右插入,所以只需要找到最右边的并返回,实现方法与findmin()方法一致。代码使用递归函数publicnodefindmin(nodet)//找到最小返回值为node,需要调用.value{if(t==null){returnnull;}elseif(t.left==null){returnt;}elsereturn(findmin(t.left));}publicnodefindmax(nodet)//求最大值{if(t==null){returnnull;}elseif(t.right==null){returnt;}elsereturn(findmax(t.right)));}求一个图中的最大值和最小值的过程如下:这里的查找过程isContains(intx)是指查找二叉搜索树中是否存在值为x的节点。具体实现上,根据二叉排序树左边小右边大的性质,向下查找。如果找到值为x的节点,则返回true,如果找不到,则返回false。当然实现可以使用Recursive或者非递归,我这里使用的是非递归的方式。publicbooleanisContains(intx)//有没有{nodecurrent=root;if(root==null){returnfalse;}while(current.value!=x&¤t!=null){if(x
