二叉樹
二叉樹性質
- 在第n層,最多有個節點
- 深度爲n層的二叉樹,最多有個節點
- 任何一個二叉樹,葉節點有個,度爲2的非葉節點有個,那麼
- 具有n個節點的完全二叉樹,的高度爲,表示向下取整
二叉樹遍歷
- 前序遍歷:中左右
- 中序遍歷:左中右
- 後序遍歷:左右中
遞歸方式
如果用遞歸方式,那麼遍歷順序是固定的,打印節點的時間決定了是那種遍歷。拿上圖來說,對於F左側,順序是FCA(A左子樹爲空)A(A右子樹爲空)ACDB(B左子樹爲空)D…
- 前序遍歷:在第一次進入打印節點
- 中序遍歷:第二次打印節點
- 後序遍歷:第三次打印節點
代碼
#include <iostream>
#include <stdlib.h>
//節點
struct Node {
int value;
Node* left;
Node* right;
Node(int v = 0): value(v), left(nullptr), right(nullptr) {}
};
//向二叉樹插入元素
void insert_tree(Node* &root, int value) {
if (nullptr == root) {
root = new Node(value);
return;
}
if (value < root->value) {
insert_tree(root->left, value);
} else if (value > root->value) {
insert_tree(root->right, value);
}
}
//生成二叉樹
void create_tree(Node* root, int root_value, int size) {
root->value = root_value++;
for (int i = 0; i <= size; ++i) {
insert_tree(root, i);
}
}
//銷燬二叉樹
void destroy_tree(Node* root) {
if (root == nullptr) {
return;
}
destroy_tree(root->left);
destroy_tree(root->right);
delete root;
}
//前序遍歷
void pre_order_recur(Node* head) {
if (head == nullptr) {
return;
}
std::cout << head->value << " ";
pre_order_recur(head->left);
pre_order_recur(head->right);
}
//中序遍歷
void in_order_recur(Node* head) {
if (head == nullptr) {
return;
}
in_order_recur(head->left);
std::cout << head->value << " ";
in_order_recur(head->right);
}
//後序遍歷
void post_order_recur(Node* head) {
if (head == nullptr) {
return;
}
post_order_recur(head->left);
post_order_recur(head->right);
std::cout << head->value << " ";
}
int main(void)
{
Node* root = new Node();
create_tree(root, 5, 9);
pre_order_recur(root);
std::cout << std::endl;
in_order_recur(root);
std::cout << std::endl;
post_order_recur(root);
std::cout << std::endl;
destroy_tree(root);
return 0;
}
非遞歸方式
非遞歸遍歷需要一個棧輔助,把節點按照順序壓入棧中。前序遍歷和後序遍歷在循環開始前都需要頭結點先入隊。
- 前序遍歷:彈出就打印,有右就壓右,有左就壓左
- 中序遍歷:根不爲空左遞歸(壓棧),根若爲空右遞歸,右遞歸時再打印
- 後序遍歷:需要兩個棧;彈出壓入s2,有左就壓左(s1),有右就壓右(s1),最後纔打印
- 層序遍歷:層序遍歷,使用隊列
1.頭結點入隊
2.頭結點彈出打印
3.左右子節點先後入隊列
4.按順序彈出打印,並將子節點先後入隊
代碼
#include <iostream>
#include <stack>
//節點
struct Node {
int value;
Node* left;
Node* right;
Node(int v = 0): value(v), left(nullptr), right(nullptr) {}
};
//向二叉樹插入元素
void insert_tree(Node* &root, int value) {
if (nullptr == root) {
root = new Node(value);
return;
}
if (value < root->value) {
insert_tree(root->left, value);
} else if (value > root->value) {
insert_tree(root->right, value);
}
}
//生成二叉樹
void create_tree(Node* root, int root_value, int size) {
root->value = root_value++;
for (int i = 0; i <= size; ++i) {
insert_tree(root, i);
}
}
//銷燬二叉樹
void destroy_tree(Node* root) {
if (root == nullptr) {
return;
}
destroy_tree(root->left);
destroy_tree(root->right);
delete root;
}
//前序遍歷
void pre_order(Node* head) {
if (head != nullptr) {
std::stack<Node*> s;
s.push(head);
while (!s.empty()) {
head = s.top();
s.pop();
std::cout << head->value << " ";
if (head->right != nullptr) {
s.push(head->right);
}
if (head->left != nullptr) {
s.push(head->left);
}
}
}
}
//中序遍歷
void in_order(Node* head) {
if (head != nullptr) {
std::stack<Node*> s;
while (!s.empty() || head != nullptr) {
if (head != nullptr) {
s.push(head);
head = head->left;
} else {
head = s.top();
s.pop();
std::cout << head->value << " ";
head = head->right;
}
}
}
}
//後序遍歷
void post_order(Node* head) {
if (head != nullptr) {
std::stack<Node*> s1;
std::stack<Node*> s2;
s1.push(head);
while (!s1.empty()) {
head = s1.top();
s1.pop();
s2.push(head);
if (head->left != nullptr) {
s1.push(head->left);
}
if (head->right != nullptr) {
s1.push(head->right);
}
}
while (!s2.empty()) {
head = s2.top();
std::cout << head->value << " ";
s2.pop();
}
}
}
//層序遍歷,使用隊列
//1.頭結點入隊
//2.頭結點彈出打印
//3.左右子節點先後入隊列
//4.按順序彈出打印,並將子節點先後入隊
void level_order(Node* head) {
std::queue<Node*> q;
q.push(head);
Node *node;
while (!q.empty()) {
node = q.front();
std::cout << node->value << std::endl;
q.pop();
if (node->left != nullptr) {
q.push(node->left);
}
if (node->right != nullptr) {
q.push(node->right);
}
}
}
int main(void)
{
Node* root = new Node();
create_tree(root, 5, 9);
pre_order(root);
std::cout << std::endl;
in_order(root);
std::cout << std::endl;
post_order(root);
std::cout << std::endl;
destroy_tree(root);
return 0;
}