1 树的表示方法:
可以将各个节点组成数组结构,包含孩子节点数据集与父节点的标号,如果有某个节点孩子节点,那么此节点里面的孩子节点数据集(可以为列表或者向量)就存储又大到小的孩子。再存储此节点的父亲节点。这时候向下查找与孩子的数目线性相关,向上查找与深度有关。

改进:每个节点主需要记录两个引用:纵向的firstchild以及横向的nextsibling(相邻兄弟),这时候储存结构的规整性大大增加。

2 二叉树:
真二叉树:每个节点都是2个度或者0个度(如果不够则在下面补满2个孩子)。更加规整(实际操作其实是假想的,并不存在)。

如何用二叉树来 描述多叉树
将长子作为左节点,次子作为右结点。

二叉树的表示:
binode类:表示树的结点
父亲、左右孩子、高度、颜色(红黑树)、npl(左式堆)
父亲、孩子均为引用。

树形结构最重要的就是遍历
定义一个树类,里面有树根(节点类)、树的高度、规模、判空函数、各种遍历方法、子树的删除插入与分离等。

前序遍历:
。。。。。。。

VLR顺序
中序:LVR
后序:LRV
即V(父亲)的顺序在哪里就是什么序遍历

先序遍历:
visit(x->data);
traverse(x->lchild,visit);
traverse(x->rchild,visit);

O(N)复杂度
但是递归在运行栈中占用空间很大。
所以非常有必要从递归改为迭代。
注意:尾递归
化解为迭代:
利用栈的方法,既然需要先处理左边,就先把右边压入栈

新的构思:
先便利左侧链,在自下而上遍历右子树。

每次访问左孩子,然后将右孩子一次压入栈。

想法:其实也可以先储存A,B表示当前层的两个节点,对A(左)节点判断有无孩子,如果有,则访问,并且A = LA, B = RA; 反之访问B结点,并且A = LB, B = RB;如果都没有,B为父节点的右兄弟节点,然后再次寻找。(自编)

对于中序遍历:
同样构建一个栈,存储右子树,
不同的是,左子树一直遍历,同时一直压入栈,直到尽头,取节点值
这时候再在返回后再pop弹出栈顶节点的值,然后将此节点右结点变为活跃节点继续进行左子树遍历。

对于后序遍历:
首先将根压栈(因为根没有右结点),然后依次:如果有左节点,就把右结点压栈,再将左节点,如果没有,就把右结点压栈,直到为空;然后对当前节点进行pop,如果pop!=父节点,那么就代表pop的是右结点,就向右结点下方继续遍历,如果是,就直接pop然后输出;

我的方法:先向左搜索到头,然后一路push,最后的直接输出,将当前节点改为父节点的右结点,在一路push,最后push后子节点已经为空,返回。输出。然后再将top(此时出来的为父节点)的节点与刚刚输出的节点比较,如果相同,证明父节点的所有子节点已经遍历完了,就再pop输出父节点,然后继续push;如果不相同,证明刚刚输出的是左端,右结点还没有遍历,遍历右结点。直到栈空。

树的重构:
中序遍历+先序/后序遍历 任意一种 便可以忠实还原原来的树形结构。
(分而治之,找到左右子树)

证法:归纳假设

对于真二叉树,可以使用先序+后序还原。(分而治之)

测试题:
并查集:


Drust
12 声望2 粉丝

闪光先生。