Non-Binary Trees #
所有非二叉树都被称为通用树。
结点的ADT:
左孩子右兄弟
// General tree node ADT
template <typename E> class GTNode {
public:-
E value(); // Return node’s value
bool isLeaf(); // True if node is a leaf
GTNode* parent(); // Return parent
GTNode* leftmostChild(); // Return first child
GTNode* rightSibling(); // Return right sibling
void setValue(E&); // Set node’s value
void insertFirst(GTNode<E>*); // Insert first child
void insertNext(GTNode<E>*); // Insert next sibling
void removeFirst(); // Remove first child
void removeNext(); // Remove right sibling
};
// General tree ADT
template <typename E> class GenTree {
public:
void clear(); // Send all nodes to free store
GTNode<E>* root(); // Return the root of the tree
// Combine two subtrees
void newroot(E&, GTNode<E>*, GTNode<E>*);
void print(); // Print a tree
};
- 深度优先遍历
- 只有前序和后序遍历
- preRoot RCS
- postRoot CSR
- 只有前序和后序遍历
- 广度优先遍历/按层遍历
数组实现 #
2个数组,1个整型变量
- 按层存放结点元素值 - 数组1
- 存放结点的双亲下标 - 数组2
- 数组尺寸 - int
指向(关注)双亲的实现方式,不关心兄弟
多棵树可以保存在同一对数组中(看index是否有效,判断是不是根)
// General tree representation for UNION/FIND
class ParPtrTree {
private:
int* array; // Node array
int size; // Size of node array
int FIND(int) const; // Find root 找到结点的根
public:
ParPtrTree(int); // Constructor
˜ParPtrTree() { delete [] array; } // Destructor
void UNION(int, int); // Merge equivalences 后者的根作为孩子连过去联合成一棵树
bool differ(int, int); // True if not in same tree
};
int ParPtrTree::FIND(int curr) const { // Find root
while (array[curr] != ROOT) curr = array[curr];
return curr; // At root
}
// FIND with path compression
int ParPtrTree::FIND(int curr) const {
if (array[curr] == ROOT) return curr; // At root
array[curr] = FIND(array[curr]);
return array[curr];
}
应用 等价类聚合 并查集
#
已知集合S={A,B,C,D,E,F,G,H,I,J},以及S上连通关系R
- 以S每个元素作为根结点构建一个(10棵树)的森林
- 依次输入R中元素,执行union操作,直到所有信息用完
- 树的最终棵树就是等价类的个数,同一棵树组成的集合,就是一个等价类
低消耗下保持联合树的高度较低
- 加权规则:把结点数小的树挂到多的树上面
- 路径压缩:find root的同时set root作为当前结点父亲
孩子链表表示法(静态) #
基于数组
多棵树可存在同一个数组中
- 指向链表的指针
左孩子/右兄弟描述法(静态) #
链式描述(动态) #
- var | size | ptr1, ptr2, …
链式描述 - 二叉ver #
- 左指针指向第一个孩子,右指针指向右边第一个兄弟
把通用树变成二叉树 #
- 1
- 最左孩 - 左孩子
- 右兄弟 - 右孩子
- 2
- 从根开始 - 从上到下从左到右 - 对每个结点进行操作1
转换后有:
- 先根 == 先序
- 后根 == 中序
森林 #
是m棵(
$$m\geq0$$)互不相交的树的集合。
任何一棵非空树可描述为一个二元组 Tree = (root, F),F为子树森林
森林与二叉树的转换 #
- 将每棵树转换成二叉树
- 从k=1开始,将第k+1棵树作为第k棵二叉树的根的右孩子
K叉树 #
- 对于一棵K叉树,任何的结点不能拥有多于k个的子树