二叉树定义
以下为本文解题代码的二叉树定义。
1 2 3 4 5 6
| struct TreeNode { int val; TreeNode* left, *right; TreeNode(int val = 0, TreeNode* left = nullptr, TreeNode* right = nullptr) : val(val), left(left), right(right) {} };
|
非递归先序遍历
题目描述
编写先序遍历二叉树的非递归算法。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| void nonRecurPre(TreeNode* root) { if (root == nullptr) return; stack<TreeNode*> s; while (root != nullptr || !s.empty()) { if (root != nullptr) { cout << root->val << " "; s.emplace(root); root = root->left; } else { root = s.top(); s.pop(); root = root->right; } } }
|
非递归后序遍历
题目描述
编写后序遍历二叉树的非递归算法。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void nonRecurPost(TreeNode* root) { if (root == nullptr) return; stack<TreeNode*> s; TreeNode* pre = nullptr; while (root != nullptr || !s.empty()) { while (root != nullptr) { s.emplace(root); root = root->left; } root = s.top(); s.pop(); if (root->right == nullptr || root->right == pre) { cout << root->val << " "; pre = root; root = nullptr; } else { s.emplace(root); root = root->right; } } }
|
反向层序遍历
题目描述
试给出二叉树的自下而上、从右到左的层序遍历算法。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| void reOrderTraversal(TreeNode* root) { queue<TreeNode*> Q; stack<int> S; Q.emplace(root); while (!Q.empty()) { TreeNode* fNode = Q.front(); S.emplace(fNode->val); Q.pop(); if (fNode->left != nullptr) { Q.emplace(fNode->left); } if (fNode->right != nullptr) { Q.emplace(fNode->right); } } while (!S.empty()) { cout << S.top() << " "; S.pop(); } }
|
非递归计算高度
题目描述
假设二叉树采用二叉链表存储结构,设计一个非递归算法求二叉树的高度。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| int nonRecurHeight(TreeNode* root) { if (root == nullptr) return 0; int res = 0; queue<TreeNode*> q, nq; q.emplace(root); while (!q.empty()) { while (!q.empty()) { TreeNode* fNode = q.front(); q.pop(); if (fNode->left != nullptr) { nq.emplace(fNode->left); } if (fNode->right != nullptr) { nq.emplace(fNode->right); } } q = move(nq); ++res; } return res; }
|
根据中序和先序序列建立二叉树
题目描述
设一棵二叉树各结点的值互不相同,其先序遍历序列和中序遍历序列分别存储于两个一维数组 A 和 B 中,试编写算法建立该二叉树的二叉链表。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| TreeNode* recurCreate(vector<int>& preOrder, int l1, int r1, vector<int>& inOrder, int l2, int r2) { if (l1 == r1) return nullptr; auto preBegin = preOrder.begin() + l1, preEnd = preOrder.begin() + r1; auto inBegin = inOrder.begin() + l2, inEnd = inOrder.begin() + r2; int x = *preBegin; TreeNode* root = new TreeNode(x); auto it = find(inBegin, inEnd, x); int lenL = it - inBegin; root->left = recurCreate(preOrder, l1 + 1, l1 + lenL + 1, inOrder, l2, l2 + lenL); root->right = recurCreate(preOrder, l1 + lenL + 1, r1, inOrder, l2 + lenL + 1, r2); return root; } TreeNode* createTree(vector<int>& preOrder, vector<int>& inOrder) { int l1 = 0, r1 = preOrder.size(); int l2 = 0, r2 = inOrder.size(); return recurCreate(preOrder, l1, r1, inOrder, l2, r2); }
|
判断完全二叉树
题目描述
二叉树按二叉链表形式存储,试编写一个判别给定二叉树是否是完全二叉树的算法。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| bool isCompleteBT(TreeNode* root) { queue<TreeNode*> Q; Q.emplace(root); bool isLeaves = false; while (!Q.empty()) { TreeNode* fNode = Q.front(); Q.pop(); if (fNode == nullptr) { isLeaves = true; continue; } if (isLeaves) return false; Q.emplace(fNode->left); Q.emplace(fNode->right); } return true; }
|
计算双分支结点数
题目描述
假设二叉树采用二叉链表存储结构存储,试设计一个算法,计算一棵给定二叉树的所有双分支结点个数。
解题代码
1 2 3 4 5 6 7 8 9
| int doubleNodeCnt(TreeNode* root) { if (root == nullptr) return 0; if (root->left != nullptr && root->right != nullptr) { return 1 + doubleNodeCnt(root->left) + doubleNodeCnt(root->right); } else { return doubleNodeCnt(root->left) + doubleNodeCnt(root->right); } }
|
交换左右子树
题目描述
设树 B 是一棵采用链式结构存储的二叉树,编写一个把树 B 中所有结点的左右子树进行交换的算法。
解题代码
1 2 3 4 5 6 7 8
| void swapLRNode(TreeNode* root) { if (root == nullptr) return; TreeNode* temp = root->left; root->left = root->right; root->right = temp; swapLRNode(root->left); swapLRNode(root->right); }
|
先序序列第k个结点值
题目描述
假设二叉树采用二叉链表存储结构,设计一个算法,求先序遍历序列中第 k (1 <= k <= 链表中结点个数)个结点的值。
解题代码
1 2 3 4 5
| int kthNodeVal(TreeNode* root, int& k) { if (root == nullptr) return 0; if (--k == 0) return root->val; return kthNodeVal(root->left, k) + kthNodeVal(root->right, k); }
|
删除特定值的结点的子树
题目描述
已知二叉树以二叉链表形式存储,编写算法完成:对于树中的每个元素值为 x 的结点,删除以它为根的子树,并释放相应的空间。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| void freeMemory(TreeNode* root) { if (root == nullptr) return; freeMemory(root->left); freeMemory(root->right); delete root; }
void deleteXNode(TreeNode* root, int x) { if (root == nullptr) return; else if (root->val == x) { freeMemory(root); return; } if (root->left != nullptr && root->left->val == x) { freeMemory(root->left); root->left = nullptr; } if (root->right != nullptr && root->right->val == x) { freeMemory(root->right); root->right = nullptr; } deleteXNode(root->left, x); deleteXNode(root->right, x); }
|
值为x的结点的祖先
题目描述
在二叉树中查找值为 x 的结点,试编写算法打印值为 x 的结点的所有祖先,假设值为 x 的结点的不多于一个。
解题代码
1 2 3 4 5 6 7 8 9 10
| bool ancestorOfXNode(TreeNode* root, int x) { if (root == nullptr) return false; if (root->val == x) return true; bool left = ancestorOfXNode(root->left, x); bool right = ancestorOfXNode(root->right, x); if (left || right) { cout << root->val << " "; } return left || right; }
|
两结点的最近公共祖先
题目描述
设 p 和 q 为指向二叉树中任意两个结点的指针,试编写算法找到 p 和 q 的最近公共祖先结点 r.
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if (root == nullptr || root == p || root == q) return root; TreeNode* left = lowestCommonAncestor(root->left, p, q); TreeNode* right = lowestCommonAncestor(root->right, p, q); if (left != nullptr && right != nullptr) { return root; } else if (left != nullptr) { return left; } else { return right; } }
|
二叉树的宽度
题目描述
假设二叉树采用二叉链表存储结构,设计一个算法,求非空二叉树 b 的宽度(即具有结点数最多的那一层的结点个数)。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| int widthOfBT(TreeNode* root) { if (root == nullptr) return 0; size_t res = 1; queue<TreeNode*> q, nq; q.emplace(root); while (!q.empty()) { while (!q.empty()) { TreeNode* fNode = q.front(); q.pop(); if (fNode->left != nullptr) { nq.emplace(fNode->left); } if (fNode->right != nullptr) { nq.emplace(fNode->right); } } q = move(nq); res = max(res, q.size()); } return res; }
|
满二叉树的后序序列
题目描述
设有一棵满二叉树(所有结点值均不同),已知其先序序列为 pre,设计一个算法求其后序序列 post.
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void getPost(vector<int>& preOrder, int p1, int q1, vector<int>& postOrder, int p2, int q2) { if (p1 > q1) return; postOrder[q2] = preOrder[p1]; int mid = (q1 - p1) / 2; getPost(preOrder, p1 + 1, p1 + mid, postOrder, p2, p2 + mid - 1); getPost(preOrder, p1 + mid + 1, q1, postOrder, p2 + mid, q2 - 1); }
vector<int> postOfFBT(vector<int>& preOrder) { int n = preOrder.size(); vector<int> res(n); getPost(preOrder, 0, n - 1, res, 0, n - 1); return res; }
|
将叶结点连接为单链表
题目描述
设计一个算法将二叉树的叶结点按从左到右的顺序连成一个单链表,表头指针为 head,二叉树按照二叉链表形式存储。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| ListNode* linkingLeaves(TreeNode* root) { queue<TreeNode*> q; q.emplace(root); ListNode* dummy = new ListNode(-1); ListNode* curNode = dummy; while (!q.empty()) { TreeNode* fNode = q.front(); q.pop(); if (fNode->left == nullptr && fNode->right == nullptr) { curNode->next = new ListNode(fNode->val); curNode = curNode->next; } if (fNode->left != nullptr) { q.emplace(fNode->left); } if (fNode->right != nullptr) { q.emplace(fNode->right); } } return dummy->next; }
|
相似二叉树
题目描述
试设计判断两棵二叉树是否相似的算法。所谓二叉树 T1 和 T2 相似,指的是 T1 和 T2 都是空的二叉树或都只有一个根节点;或者 T1 的左子树和 T2 的左子树是相似的,且 T1 的右子树和 T2 的右子树是相似的。
解题代码
1 2 3 4 5 6 7 8 9
| bool similarBT(TreeNode* root1, TreeNode * root2) { if (root1 == nullptr && root2 == nullptr) return true; if ((root1 == nullptr) ^ (root2 == nullptr)) return false; if (root1->left == nullptr && root1->right == nullptr && root2->left == nullptr && root2->right == nullptr) { return true; } return similarBT(root1->left, root2->left) && similarBT(root1->right, root2->right); }
|
二叉树的带权路径长度和
题目描述
二叉树的带权路径长度(WPL)是二叉树中所有叶结点的带权路径长度之和,给定一棵二叉树,其叶结点的 val 域保存该结点的非负权值。设 root 为指向 T 的根节点的指针,设计求 T 的 WPL 的算法。
解题代码
BFS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| int getWPL(TreeNode* root) { queue<TreeNode*> q, nq; q.emplace(root); int res = 0; for (int len = 0; !q.empty(); ++len) { while (!q.empty()) { TreeNode* fNode = q.front(); q.pop(); if (fNode->left == nullptr && fNode->right == nullptr) { res += fNode->val * len; } if (fNode->left != nullptr) { nq.emplace(fNode->left); } if (fNode->right != nullptr) { nq.emplace(fNode->right); } } q = move(nq); } return res; }
|
DFS
1 2 3 4 5 6 7 8 9 10 11
| int dfs(TreeNode* root, int depth) { if (root == nullptr) return 0; if (root->left == nullptr && root->right == nullptr) { return root->val * depth; } return dfs(root->left, depth + 1) + dfs(root->right, depth + 1); }
int getWPL(TreeNode* root) { return dfs(root, 0); }
|
表达式树转表达式
题目描述
请设计一个算法,将给定表达式树转换为对应的中缀表达式并输出。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void dfs(TreeNode<char>* root, int depth) { if (root == nullptr) return; if (root->left == nullptr && root->right == nullptr) { cout << root->val; } else { if (depth > 1) cout << "("; dfs(root->left, depth + 1); cout << root->val; dfs(root->right, depth + 1); if (depth > 1) cout << ")"; } }
void getInfixExp(TreeNode<char>* root) { dfs(root, 1); }
|
判定顺序存储二叉树是否为二叉搜索树
题目描述
已知非空二叉树 T 结点值均为正整数,采用顺序存储方式存储,T 中不存在的结点在数组中用 -1 表示。请设计一个尽可能高效的算法,判定一棵采用这种方式存储的二叉树是否为二叉搜索树。
解题代码
1 2 3 4 5 6 7 8 9 10 11
| bool dfs(vector<int>& T, int idx, int& lastVal) { if (idx - 1 >= T.size() || T[idx - 1] == -1) return true; if (!dfs(T, idx * 2, lastVal) || T[idx - 1] <= lastVal) return false; lastVal = T[idx - 1]; return dfs(T, idx * 2 + 1, lastVal); }
bool isBST(vector<int>& T) { int lastVal = INT32_MIN; return dfs(T, 1, lastVal); }
|
根据层序序列建立二叉树
题目描述
设一棵二叉树层序遍历序列存储于一个一维数组中,空结点用 INT32_MAX 表示,试编写算法建立该二叉树的二叉链表。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| TreeNode* createTreeByOrder(vector<int>& order) { if (order.front() == INT32_MAX) return nullptr; queue<TreeNode*> q; int idx = 0; TreeNode* root = new TreeNode(order[idx++]); q.emplace(root); while (!q.empty()) { TreeNode* fNode = q.front(); q.pop(); if (fNode == nullptr) continue; if (idx < order.size()) { TreeNode* lChild = nullptr; if (order[idx] != INT32_MAX) { lChild = new TreeNode(order[idx]); } fNode->left = lChild; q.emplace(lChild); ++idx; } if (idx < order.size()) { TreeNode* rChild = nullptr; if (order[idx] != INT32_MAX) { rChild = new TreeNode(order[idx]); } fNode->right = rChild; q.emplace(rChild); ++idx; } } return root; }
|