很长时间没有写关于数据结构的文章了, 那是因为最近实在是太忙了, 而梳理数据结构这方面的知识点又很庞大驳杂,只能尽可能地总结的,压缩。与此同时这又需要很长的准备时间。
树与二叉树决定分两部分,分为概念篇和数据结构算法篇。
我们先来熟悉一下树与二叉树部分相关的概念和结构。
树 是n (n>=0)个结点的有限集合。n=0 时为空树。 在任意一颗非空的树中:1.有且仅有一个特殊成为根Root 的结点;2. 当n>1时, 其余结点又可以分为m>0个互不想交的有限集,T1,T2,T3,,,,Tm, 其中每一有限集又是一棵树,并且称为根的子树 SubTree
结点拥有的子树数称为结点的度。度为0的结点称为叶子结点或终端结点,度不为0的结点称为非终端结点或分支结点。除根结点以外,分支结点也称为内部结点。树的度是树内各结点的度的最大值。
节点的层次 level 从根节点开始定义起,根为第一层,根的孩子为第二层。 若某节点在第I层,则其子树的根就在第I+1层。 其双亲在同一层的节点互为堂兄弟。
树中节点的最大层次成为树的深度 depth 或者高度。
如果将树中节点的各子树看成从左至右是有次序的,不能互换的,则称为该树为有序树,否则为无序树。
森林是M >=0 个不想交的树的集合
看过我前几篇数据解析的都知道,线性表和hash表的数据结构。但是对于树的存储,很显然
简单的顺序存储不能满足树的实现 而且需要结合顺序存储和链式存储来实现。
树的存储结构 常用三种表示方法。
在每个结点中,附设一个指示器指示其双亲结点到链表中的位置。
data- parent
data- left_child - right_child
data-firstchild-rightslib
任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的右兄弟如果存在也是唯一的。因此,我们设置两个指针,分别指向该结点的第一个孩子和此结点的右兄弟
二叉树(binary tree) 是 n(n>=0) 个节点的有限集合,该集合或者空集称为空二叉树, 或者由一个根节点和两颗互不想交的、分别称为根节点的左子树和右子树的二叉树组成。
所有的结点都只有左子树的二叉树叫左斜树。所有结点都是只有右子树的二叉树叫右斜树。这两者统称为斜树
其实这种树,想想看是不是和链表很一样。
在一棵二叉树中,如果所有分支节点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树成为满二叉树。
对于一颗具有n个节点的二叉树按照层序编号,如果编号为i(1<=i<=n)的节点与同样深度的满二叉树中编号为IDE节点在二叉树中位置完全相同,则这可二叉树成为完全二叉树。
这一部分是照搬课本的, 也不必死记硬背。 就是根据性质来就行了。
规则是若二叉树为空,则空操作返回,否则先访问跟结点,然后前序遍历左子树,再前序遍历右子树
规则是若树为空,则空操作返回,否则从根结点开始(注意并不是先访问根结点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树
规则是若树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点
规则是若树为空,则空操作返回,否则从树的第一层,也就是根结点开始访问,从上而下逐层遍历,在同一层,按从左到右的顺序对结点逐个访问
判断一颗二叉树能不能转换成一颗树还是森林,就只要看这个二叉树的根节点有没有右孩子,有就是森林,没有就是一棵树。转换步骤。
1. 从根节点开始,若右孩子存在,则把与右孩子连接的线删除,再查看分离后的二叉树,若右孩子存在,则连线删除。。。。,直到所有右孩子连线都删除为止,得到分离的二叉树。
2. 再将每颗分离后的二叉树转换为树即可。
给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
红黑树是一种自平衡的二叉查找树。
1.节点是红色或黑色。
2.根节点是黑色。
3.每个叶子节点都是黑色的空节点(NIL节点)。
4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
红黑树的自平衡部分牵涉到很多情况,这里就先不说了。下一篇文章会结合Java 中的TreeMap 进行详细分析红黑树部分算法。
数据结构这部分的确很多复杂的东西。这一部分仅仅是部分概念部分,记录下来算是复习吧, 如果有不对的地方,欢迎批评指正。
赫夫曼树的构建
维基百科-红黑树