二叉树序列化题解
题意理解:层序遍历,就是从上往下,从左往右,遇到数字输出数字,空节点输出# 应该没人不理解
先序遍历:就是根左右,空的用# 代替,有人可能疑惑6 后面为啥3个 # 原因是,6 有两个空树,另外一个# 代表 4 的右子树
解题思路:
1.根据层序遍历,创建二叉树。
毫无疑问,第一个节点必定是根节点,层序遍历采用队列的思想,
1.1 : 先把跟节点入队,
当队列不空
1.2 取出队头节点,这个节点作为二叉树的待建立的树节点。这个说法怎么理解看你的悟性了,称此节点为 R
1.3 从 层序遍历 中拿到一个字符串,可以断定这就是R 的左子树的值,(理解这部,你可以按照堆的思想理解,或者在草稿纸上画一下。)
如果这个字符串不是 # 那么将它作为节点入队。
如果是# 就把它忽略掉。
不管是不是 # 那么最终 都要把它作为 R 的左节点插入到 R 的左树中
插完后,再继续从层序遍历中取出下一个节点 (可以断定这就是R 的 右子树的值 )
如果这个字符串不是 # 那么将它作为节点入队。
如果是# 就把它忽略掉。
不管是不是 # 那么最终 都要把它作为 R 的右节点插入到 R 的右树中 2. 先序遍历输出 二叉树,
2.1 递归输出
递归出口:遇到空树 输出# 返回
先输出当前节点,然后递归左边,再递归右边。
2.2 用栈 就可以不递归输出
把根节点入栈,
每次弹出栈顶元素,
如果有数值,输出,并且将左右子树的根节点入栈。
如果没有数值,输出 # 进入下一次循环。
具体做法:
struct node
{
int l, r;
string val;
}; 代表输的一个节点,用数组模拟二叉树 val 代表 数值, l 和 r 代表左右子树的下标,下表如果是 0 代表空树,这一部分应该大家都有基础,不再赘述,如有不懂欢迎留言。
{
int l, r;
string val;
}; 代表输的一个节点,用数组模拟二叉树 val 代表 数值, l 和 r 代表左右子树的下标,下表如果是 0 代表空树,这一部分应该大家都有基础,不再赘述,如有不懂欢迎留言。
遇到的坑: 就写在代码注释里面把
#include<iostream> #include<queue> #include<stack> using namespace std; const int N = 1e5 + 10; int root = 1, idx = 1; struct node { int l, r; string val; }; node tr[N]; queue< node* > q; string tree[N]; stack<node*> st; void addnode(node* root, string val, int opt) { //着重解释 opt 的含义 如果是 1 代表将她插入到 root 的左树中,2 代表插入到右树中 int u = ++idx; if (opt == 1) { root->l = u; } else { root->r = u; } tr[u].l = tr[u].r = 0; //作为一个新的节点 左右两树应该置位空 tr[u].val = val; } void output() { st.push(&tr[1]); while (st.size()) { node* t = st.top(); st.pop(); if (t->val.size() == 0) cout << "#" << endl; else { cout << t->val << endl; st.push(&tr[t->r]); st.push(&tr[t->l]); } } } int main() { int n; cin >> n; string s; cin >> s; tr[root].l = tr[root].r = 0; tr[root].val = s; q.push(&tr[root]); for (int i = 2; i <= n; i++) cin >> tree[i]; //规定 1是根节点,所以从2 开始 int cur = 2; while (q.size()) //如果写成 while(true) 会发生段错误 { node* t = q.front(); q.pop(); string l = tree[cur++]; if (l != "#") { addnode(t, l, 1); q.push(&tr[t->l]); } if (cur > n) break; //坑 :注意如果 这个下标已经超过 n 那么已经说明所有节点遍历完了,不要继续了 string r = tree[cur++]; if (r != "#") { addnode(t, r, 2); q.push(&tr[t->r]); } if (cur > n) break; } output(); return 0; }