二叉樹的遍歷有前序遍歷(遍歷順序:根->左->右),中序遍歷(遍歷順序:左->根->右),後序遍歷(遍歷順序:左->右->根),可以看出,這裏的“前/中/後”是對根的位置而言的。哦對,還有一種遍歷方法叫做層序遍歷,下面就來C++實現下。(代碼中除了各種遍歷方法,還有求樹深,樹的鏡像二叉樹的鏡像(劍指offer),以及根據兩個遍歷序列重構二叉樹的實現)
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
//定義樹的節點
typedef struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
} TreeNode;
void FrontPrint(TreeNode* root){
if(root == nullptr){
return;
}
//根
printf("%d ", root->val);
//左
FrontPrint(root->left);
//右
FrontPrint(root->right);
}
void FrontPrintByStack(TreeNode* root){
//前序遍歷的非遞歸實現,藉助stack
stack<TreeNode*> s;
TreeNode* cur = root;
while (cur!= nullptr || !s.empty()){
//把左子樹壓棧,直至無左子樹
while (cur != nullptr){
printf("%d ", cur->val);//根
s.push(cur);
cur = cur->left;
}
//訪問右子樹
cur = s.top()->right;
s.pop();//出棧
}
}
void MidPrint(TreeNode* root){
//左根右
if(root== nullptr) return;
//左
MidPrint(root->left);
//根
printf("%d ", root->val);
//右
MidPrint(root->right);
}
void MidPrintByStack(TreeNode* root){
//左根右
stack<TreeNode*> s;
TreeNode* cur = root;
while (cur != nullptr || !s.empty()){
while(cur != nullptr){
s.push(cur);
cur = cur->left;
}
cur = s.top();
s.pop();
printf("%d ", cur->val);
cur = cur->right;
}
}
void BackPrint(TreeNode* root){
if(root== nullptr) return;
//左
BackPrint(root->left);//遞歸調用其實是一次壓棧
//右
BackPrint(root->right);
//根
printf("%d ", root->val);
}
void BackPrintByStack(TreeNode* root){
//左右根 參考https://blog.csdn.net/monster_ii/article/details/82115772
stack<TreeNode*> s;
TreeNode* cur = root;
TreeNode* top, *last= nullptr;//last可以表示是從左子樹返回根節點還是從右子樹返回根節點
while (cur != nullptr || !s.empty()){
while(cur != nullptr){
s.push(cur);
cur = cur->left;
}
top = s.top();//棧中保存的元素是它的右子樹和自身都沒有被遍歷到的節點
if (top->right == nullptr || top->right == last){
s.pop();
printf("%d ", top->val);
last = top;
}
else {
cur = top->right;
}
}
}
void LevelPrintbByQueue(TreeNode* root){
//層序遍歷二叉樹並輸出 用隊列實現
queue<TreeNode*> q;
if(root != nullptr){
q.push(root);
}
while(!q.empty()){
TreeNode *tmp = q.front(); //隊首
printf("%d ", tmp->val);
if(tmp->left != nullptr){
q.push(tmp->left);
}
if(tmp->right != nullptr){
q.push(tmp->right);
}
q.pop();
}
printf("\n");
}
void LevelPrintbByArray(TreeNode* root){
//層序遍歷二叉樹並輸出 用數組實現 https://blog.csdn.net/m0_37925202/article/details/80796010
TreeNode* a[100];
int in=0, out=0;//in表示進入數組的元素數,out表示出數組的元素數,[out,in]區間就是模擬的當前的隊列
if(root != nullptr){
a[in++] = root;
}
while(in > out){
printf("%d ",a[out]->val);
if(a[out]->left != nullptr){
a[in++] = a[out]->left;
}
if(a[out]->right != nullptr){
a[in++] = a[out]->right;
}
out++;
}
}
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
//根據前序遍歷pre和中序遍歷vin重建二叉樹
//遞歸方法
//停止條件
if(pre.size() == 0){
return nullptr;
}
//解題步驟
vector<int> lpre,lvin,rpre,rvin;
//確定root
TreeNode* root = new TreeNode(pre[0]);
//在中序中找到root的位置,以及左右子樹
int loc = 0;//root在中序遍歷的位置
int flag = 0;
//對於中序遍歷數組,下標0到loc,其中下標0到loc-1是左子樹,loc是根節點
for(int i=0;i<vin.size();i++){
if(vin[i] == root->val){
loc = i;
flag = 1;
}
else{
if(flag == 0){
lvin.push_back(vin[i]);
}
else{
rvin.push_back(vin[i]);
}
}
}
//對於前序遍歷數組,下標0到loc,其中0是根節點,1-loc是左子樹
for(int i = 1;i < pre.size();i++){
if(i <= loc){
lpre.push_back(pre[i]);
}
else
rpre.push_back(pre[i]);
}
//得到左右子樹
root->left = reConstructBinaryTree(lpre,lvin);
root->right = reConstructBinaryTree(rpre,rvin);
//返回以root爲根節點的樹
return root;
}
void Mirror(TreeNode *pRoot) {
//樹的鏡像
queue<TreeNode *>q;//使用隊列對樹進行層序遍歷
if(pRoot == nullptr){
return;
}
else{
q.push(pRoot);
}
while(!q.empty()){
TreeNode* f = q.front();
if(f->left!=nullptr || f->right!=nullptr){
//只要不是葉節點,就交換左子樹和右子樹
TreeNode* tmp = f->left;
f->left = f->right;
f->right = tmp;
tmp = nullptr;
}
if(f->left != nullptr)
q.push(f->left);
if(f->right != nullptr)
q.push(f->right);
q.pop();
}
}
int maxn = 0;
int len = 0;
//樹深=樹中最長的路徑長度
int TreeDepth(TreeNode* pRoot)
{
if(pRoot==nullptr){
//該條路徑搜索結束
if(len>maxn){
maxn=len;
}
}
else{
len++;//當前節點在路徑上
TreeDepth(pRoot->left);//雖然有return但不一定要用變量去接受這個返回值
TreeDepth(pRoot->right);
len--;//返回上一個節點,即當前節點不在路徑上
}
return maxn;
}
int main(){
vector<int> pre = {1,2,3,4,5,6,7};//前序遍歷
vector<int> vin = {3,2,4,1,6,5,7};//中序遍歷
TreeNode* ans = reConstructBinaryTree(pre,vin);
LevelPrintbByQueue(ans);
LevelPrintbByArray(ans);
printf("\n");
FrontPrint(ans);
printf("\n");
FrontPrintByStack(ans);
printf("\n");
MidPrint(ans);
printf("\n");
MidPrintByStack(ans);
printf("\n");
BackPrint(ans);
printf("\n");
BackPrintByStack(ans);
printf("\n");
printf("depth=%d\n", TreeDepth(ans));
Mirror(ans);
LevelPrintbByQueue(ans);
}