树的表示法
-
双亲表示法
-1表示根节点。
-
孩子表示法
-
孩子兄弟表示法
注意,此种表示法是将树和森林转化为二叉树的写法。即对于每个结点,其lc为它的第一个孩子,rc代表的子树为它的兄弟结点。
树,森林与二叉树转换
见书P162.
关于遍历问题:
- 树的先根遍历
即先访问根结点,再访问树的子节点(从左往右),对于每一颗子树也如此。
树的先根遍历序列,与将其转化为二叉树之后的先序序列相同。 - 树的后根遍历
即先从最左结点开始,从左往右访问子节点,最后访问根节点。
树的后根遍历序列,与将其转化为二叉树之后的中序序列相同。 - 树的层序遍历
从上到下,从左到右。同样与其二叉树形式的层序序列相同。 - 森林的先根遍历
按顺序对每棵树做先根遍历的序列。
森林的先根序列,与将森林转为二叉树的先根序列相同。 - 森林的后根遍历(也称中根遍历)
对每棵树做先子节点最后根节点的遍历。
森林的后根序列,与其二叉树形式的中序序列相同。
并查集*
题解
- 设F为一个森林,B为其转化而来的二叉树。若F中有n个非终端结点,求B中无右孩子的结点个数。
首先明确在二叉树中无右孩子,即是在森林中无兄弟的结点。
森林中的最后一棵树,在转化为二叉树时必无右孩子。
每棵树中的最后一个叶子节点必无兄弟。
因此B中无右孩子的个数为n+1. - 当树转换为二叉树时,根节点无右孩子;树的每个分支结点(子树中结点>1)的最右结点无右孩子。 且若题中给出了树的结点为n,叶节点为x,则分支结点数=n-x.(?)
- 编程求以孩子兄弟表示法存储的森林的叶子结点数。
注意孩子兄弟表示法的实质是将树或者森林转化为二叉树的形式存储。
因此题中要求的是原来的森林的叶子节点数,即在二叉树中没有左子树(没有孩子)的所有结点。
//孩子兄弟表示法的数据单元
struct tree{
int data;
tree* firstchild; //左子树连接第一个孩子
tree* bro;//右子树连接兄弟
}
- 求二叉树高度
第一种:直接递归。
第二种:后序遍历。由于后序遍历的自下而上特性,当某一结点出栈时,栈中结点皆为其到根节点路径上的途经结点,由此可求出最大深度。
//直接递归
int recur_height(Bitree* root) {
if (root == nullptr) {
return 0;
}
else {
int lc = recur_height(root->lc);
int rc = recur_height(root->rc);
return lc < rc ? rc + 1 : lc + 1;
};
}
//后序遍历
int max_height = 0;
int behind_height(Bitree* root) {
stack<Bitree*> s;
Bitree* pre = nullptr;
Bitree* p = root;
while (p || !s.empty()) {
if (p) {
s.push(p);
p = p->lc;
}
else {
p = s.top();
if (p->rc == nullptr || (pre!=nullptr&&p->rc == pre)) {
s.pop();
cout << p->data;
//出栈时,可以开始比对深度
if (s.size() + 1 > max_height)max_height = s.size() + 1;
p = nullptr;
}
else {
p = p->rc;
};
}
}
}
- 练习:已知一棵树的层次序列和每个结点的度,编写构造此树的孩子兄弟链表