前言 二叉樹遍歷,一般分爲廣度優先遍歷(BFS)和深度優先遍歷(DFS),其中深度優先遍歷---前中後序遍歷,一條道走到黑,前中後序遍歷大部分會用到遞歸的方式,當然也會用非遞歸的棧的方式來實現,只不過非遞歸的時間複雜度更高;廣度優先遍歷---層次遍歷,依賴隊列的方式來實現;
// 1
// / \
// 2 3
// / \ \
//4 5 6
// 前序遍歷順序:[1 2 4 5 3 6]
// 中序遍歷順序:[4 2 5 1 3 6]
// 後序遍歷順序:[4 5 2 6 3 1]
// 層次遍歷順序:[1 2 3 4 5 6]
1.層序遍歷
解釋:根據返回的結果,層序遍歷輸出各節點的值,首個值是所返回的根節點的值。
其中:null 表示是空節點
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector <vector <int>> ret;
if (!root) return ret;
queue <TreeNode*> q;
q.push(root);
while (!q.empty()) {
int currentLevelSize = q.size();
ret.push_back(vector <int> ());
for (int i = 1; i <= currentLevelSize; ++i) {
auto node = q.front(); // 隊列的頭
q.pop();
ret.back().push_back(node->val); //pop出隊列的節點時,把隊列中節點的值存於二維vector,back()函數表示得到數組的最後一個單元的引用
cout << node->val << endl;
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
}
return ret;
}
};
int main() {
vector<string> vec = {"3","9","20","null","null","15","7"}; // [[3],[9,20],[15,7]]
// 初始化一棵樹
// 3
// / \
// 9 20
// / \
// 15 7
TreeNode* root = new TreeNode(3);
TreeNode* a1 = new TreeNode(9);
TreeNode* a2 = new TreeNode(20);
TreeNode* b1 = new TreeNode(15);
TreeNode* b2 = new TreeNode(7);
root->left = a1;
root->right = a2;
a2->left = b1;
a2->right = b2;
Solution solution;
vector<vector<int>> matrix = solution.levelOrder(root);
}
2.前中後前序遍歷(遞歸方式)
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
/// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
/// Simulation
/// Time Complexity: O(n^2)
/// Space Complexity: O(n)
class Solution {
public:
TreeNode* insertIntoMaxTree(TreeNode* root, int val) {
vector<int> vec = {14,3,8,2,9};
dfs(root, vec);
vec.push_back(val);
return construct(vec, 0, vec.size() - 1);
}
TreeNode* construct(const vector<int>& A, int l, int r){
if(l > r) return NULL;
int best_val = A[l], best_index = l;
for(int i = l + 1; i <= r; i ++)
if(A[i] > best_val)
best_val = A[i], best_index = i;
TreeNode* retNode = new TreeNode(A[best_index]);
retNode->left = construct(A, l, best_index - 1);
retNode->right = construct(A, best_index + 1, r);
return retNode;
}
void dfs(TreeNode* root, vector<int>& A){
if(!root) return;
dfs(root->left, A);
A.push_back(root->val);
dfs(root->right, A);
}
// 前序遍歷
void print1BST(TreeNode* root) {
if (!root) {
return;
}
cout << "print1BST: "<< root->val << endl;
if (root->left) {
print1BST(root->left);
}
if (root->right) {
print1BST(root->right);
}
}
// 中序遍歷
void print2BST(TreeNode* root) {
if (!root) {
return;
}
if (root->left) {
print3BST(root->left);
}
cout << "print2BST: "<< root->val << endl;
if (root->left) {
print3BST(root->right);
}
}
// 後序遍歷
void print3BST(TreeNode* root) {
if (!root) {
return;
}
if (root->left) {
print3BST(root->left);
}
if (root->left) {
print3BST(root->right);
}
cout << "print3BST: "<< root->val << endl;
}
// 層序遍歷
// 1)首先利用隊列先進先出的規則,把根節點放進隊列,然後用一個vector來保存根節點的值,
// 2)然後取出根節點的左節點和右節點放進隊列,當pop根節點後,此時輪到保存左節點和右節點的值,然後pop,直到隊列爲空,繼續下一層遍歷
void printLevel(TreeNode* root) {
vector<int> vec;
if(root == nullptr) {
return;
}
queue<TreeNode*> que;
que.push(root);
while(!que.empty()) {
TreeNode* cur = que.front();
que.pop();
vec.push_back(cur->val);
cout << "printLevel: " << cur->val << endl;
if (cur->left) {
que.push(cur->left);
}
if (cur->right) {
que.push(cur->right);
}
}
}
3. 非遞歸的前中後序遍歷
// 非遞歸的前序遍歷
// 1)利用棧Stack先進後出的規則,先把根節點入棧,然後取出值存於vector,然後再把右節點和右左節點入棧,依次pop,直到棧爲空
// 2)後序遍歷可以將前序遍歷改成 root -> right -> left,然後反轉一下,就成了後序遍歷 left->right->root
void preOrder(TreeNode *root) {
stack<TreeNode*> stackPointer;
vector<int> vec;
if (root == nullptr){
return;
}
stackPointer.push(root);
while (!stackPointer.empty()) {
TreeNode *node = stackPointer.top();
if(node == nullptr) {
continue;
}
vec.push_back(node->val);
stackPointer.push(node->right); // 先右子樹,後左子樹入棧,保持前序遍歷 root -> left -> right
stackPointer.push(node->left);
stackPointer.pop();
}
for (int i = 0; i > 0; ++i) {
cout << "preOrder: " << vec[i] << endl;
}
}
// 非遞歸的中序遍歷 left->root->right 入棧時,先入root,然後把left賦給root,此時出棧的是left->root
void inOrder(TreeNode *root) {
stack<TreeNode*> stack;
if (root == nullptr) {
return;
}
TreeNode *cur = root;
while (!stack.empty()) { // 保持 入棧 root->left,出棧left->root->right
while (cur != nullptr) {
stack.push(cur);
cur = cur->left;
}
TreeNode *node = stack.top();
// vec.push_back(node->val);
cout << "inOrder: " << node->val << endl;
cur = node->right;
}
}
// 非遞歸的後序遍歷 left->right->root
void postOrder(TreeNode *root) {
stack<TreeNode*> stackPointer;
vector<int> vec;
if (root == nullptr){
return;
}
stackPointer.push(root);
while (!stackPointer.empty()) {
TreeNode *node = stackPointer.top();
if(node == nullptr) {
continue;
}
vec.push_back(node->val);
stackPointer.push(node->left); // 先左子樹,後右子樹入棧,保持出棧前序遍歷 root -> right -> left,反轉一下
stackPointer.push(node->right);
stackPointer.pop();
}
for (int i = 0; i > 0; --i) {
cout << "postOrder: " << vec[i] << endl;
}
}
4.二叉樹的插入操作
/// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
TreeNode* insertIntoMaxTree(TreeNode* root, int val) {
vector<int> vec = {14,3,8,2,9};
dfs(root, vec);
vec.push_back(val);
return construct(vec, 0, vec.size() - 1);
}
TreeNode* construct(const vector<int>& A, int l, int r){
if(l > r) return NULL;
int best_val = A[l], best_index = l;
for(int i = l + 1; i <= r; i ++)
if(A[i] > best_val)
best_val = A[i], best_index = i;
TreeNode* retNode = new TreeNode(A[best_index]);
retNode->left = construct(A, l, best_index - 1);
retNode->right = construct(A, best_index + 1, r);
return retNode;
}
void dfs(TreeNode* root, vector<int>& A){
if(!root) return;
dfs(root->left, A);
A.push_back(root->val);
dfs(root->right, A);
}