二叉树(C++):创建,前中后序遍历(递归+非递归),获取叶子节点个数,获取树的高度
文章目錄
- 前言
- 創(chuàng)建二叉樹(shù)
- 先序遍歷
- 中序遍歷
- 后序遍歷
- 獲取葉子節(jié)點(diǎn)個(gè)數(shù)
- 獲取樹(shù)的高度
- 測(cè)試代碼
前言
現(xiàn)有如下二叉樹(shù):
關(guān)于二叉樹(shù)的相關(guān)操作,我們能夠發(fā)現(xiàn)二叉樹(shù)從根節(jié)點(diǎn)到子節(jié)點(diǎn),以及每個(gè)中間節(jié)點(diǎn)基本都能夠拆分為若干個(gè)子節(jié)點(diǎn)的操作,且每個(gè)子節(jié)點(diǎn)的操作都和其頭節(jié)點(diǎn)操作一致。
所以我們針對(duì)二叉樹(shù)的操作都可以使用分治算+回溯/歸并算法進(jìn)行
完整測(cè)試代碼見(jiàn)文末
創(chuàng)建二叉樹(shù)
二叉樹(shù)數(shù)據(jù)結(jié)構(gòu):
typedef struct tree
{char data;struct tree *left;struct tree *right;
}Tree,*TreeNode;
我們使用先序方式,創(chuàng)建如上二叉樹(shù):
輸入如下: ABD***CE**FG***
創(chuàng)建過(guò)程
/*創(chuàng)建二叉樹(shù)*/
void createTree(TreeNode *root) {char val = 0;cin >> val; //持續(xù)輸入,直到完成一個(gè)二叉樹(shù)的構(gòu)建if (val == '*') {//輸入為*則代表當(dāng)前節(jié)點(diǎn)為空(*root) = NULL;} else {(*root) = (Tree *)malloc(sizeof(tree));if ((*root) == NULL) {cout << "create node failed " << endl;exit(-1);} else {(*root)->data = val;//為輸入的節(jié)點(diǎn)賦值createTree(&(*root)->left);//分治左孩子節(jié)點(diǎn)createTree(&(*root)->right);//分治右孩子節(jié)點(diǎn)}}
}
先序遍歷
先序遍歷二叉樹(shù)指:先遍歷二叉樹(shù)的根節(jié)點(diǎn),再遍歷當(dāng)前根節(jié)點(diǎn)所有左子樹(shù),再遍歷當(dāng)前根節(jié)點(diǎn)所有右子樹(shù)
因?yàn)檫@個(gè)過(guò)程針對(duì)子節(jié)點(diǎn)的遍歷和根節(jié)點(diǎn)是沒(méi)有任何區(qū)別的,所以可以使用分治進(jìn)行處理
/*遞歸先序遍歷*/
void preOrder(Tree *root) {if (root == NULL) {return;}cout << root->data;preOrder(root->left);preOrder(root->right);
}
同樣可以使用棧進(jìn)行非遞歸的先序遍歷,即
棧可以保存遍歷過(guò)程中的左節(jié)點(diǎn),因?yàn)橄刃虮闅v是先訪(fǎng)問(wèn)根節(jié)點(diǎn),其次就是左節(jié)點(diǎn)
while(p) {cout << p ->data; //訪(fǎng)問(wèn)根節(jié)點(diǎn)s.push(p); //保存左子節(jié)點(diǎn)p = p->left;
}
接著再?gòu)棗?#xff0c;直到獲取一個(gè)右節(jié)點(diǎn)
while(!s.empty()) {p = s.top();s.pop();p = p -> right;
}
接著再重復(fù)對(duì)右節(jié)點(diǎn)進(jìn)行同樣的訪(fǎng)問(wèn)操作,具體過(guò)程如下
/*非遞歸先序遍歷*/
void preOrderNoRecur(Tree *root) {if (root == NULL) {return;}stack<TreeNode> s;Tree *p = root;while(!s.empty() || p) {while(p) {cout << p ->data;s.push(p);p = p->left;}while(!s.empty()) {p = s.top();s.pop();p = p -> right;}}cout << endl;
}
中序遍歷
中序遍歷二叉樹(shù)是指:先訪(fǎng)問(wèn)左節(jié)點(diǎn),中間訪(fǎng)問(wèn)根節(jié)點(diǎn),最后訪(fǎng)問(wèn)右節(jié)點(diǎn)
分治過(guò)程如下:
void inorder(Tree *root) {if (root == NULL) {return;}inorder(root -> left);cout << root -> data;inorder(root -> right);
}
中序遍歷二叉樹(shù)的非遞歸方式和先序類(lèi)似,支持訪(fǎng)問(wèn)的時(shí)機(jī)是在先訪(fǎng)問(wèn)第一輪所有的左節(jié)點(diǎn),再獲取右節(jié)點(diǎn)之前進(jìn)行根節(jié)點(diǎn)的訪(fǎng)問(wèn),實(shí)現(xiàn)過(guò)程如下:
/*非遞歸中序遍歷*/
void inorderNoRecur(Tree *root) {if (root == NULL) {return;}stack<TreeNode> s;Tree *p = root;while(!s.empty() || p) {while(p) {s.push(p);p = p ->left;}while(!s.empty()) {p = s.top();cout << p->data;s.pop();p = p->right;}}cout << endl;
}
后序遍歷
后序遍歷二叉樹(shù)是指:先訪(fǎng)問(wèn)左節(jié)點(diǎn),再訪(fǎng)問(wèn)右節(jié)點(diǎn),最后訪(fǎng)問(wèn)根節(jié)點(diǎn)
分治過(guò)程如下:
/*遞歸后序遍歷*/
void lastorder(Tree *root) {if (root == NULL) {return;}lastorder(root -> left);lastorder(root -> right);cout << root -> data;
}
非遞歸的訪(fǎng)問(wèn)過(guò)程和先序/中序遍歷有差異,因?yàn)楹笮虮闅v需要優(yōu)先訪(fǎng)問(wèn)完左節(jié)點(diǎn)、右節(jié)點(diǎn)
所以根節(jié)點(diǎn)的訪(fǎng)問(wèn)前提是:
- 右子節(jié)點(diǎn)為空
- 右子節(jié)點(diǎn)已經(jīng)訪(fǎng)問(wèn)過(guò)
所以實(shí)現(xiàn)的過(guò)程中需要保存已經(jīng)訪(fǎng)問(wèn)過(guò)的右子節(jié)點(diǎn)
void lastorderNoRecur(Tree *root) {if (root == NULL) {return;}stack<TreeNode> s;Tree *p = root;Tree *lastvisit = NULL;//保存已經(jīng)訪(fǎng)問(wèn)過(guò)的右子節(jié)點(diǎn)/*先獲取到左子節(jié)點(diǎn)*/while(p) {s.push(p);p = p ->left;}while(!s.empty()) {p = s.top();s.pop();/*右節(jié)點(diǎn)已經(jīng)為空或者已經(jīng)訪(fǎng)問(wèn)過(guò),那么認(rèn)為右節(jié)點(diǎn)已經(jīng)訪(fǎng)問(wèn)完,可以訪(fǎng)問(wèn)根節(jié)點(diǎn)了*/if (p -> right == NULL || p ->right == lastvisit) {cout << p->data;lastvisit = p;} else {//否則,將右節(jié)點(diǎn)以及右節(jié)點(diǎn)的子節(jié)點(diǎn)入棧從而繼續(xù)訪(fǎng)問(wèn)s.push(p);p = p -> right;/*每獲取到一個(gè)非空右節(jié)點(diǎn),就將該右節(jié)點(diǎn)的左節(jié)點(diǎn)放入棧中*/while(p) {s.push(p);p = p -> left;}}}cout << endl;
}
獲取葉子節(jié)點(diǎn)個(gè)數(shù)
葉子節(jié)點(diǎn)的條件就是:左右子樹(shù)都為空
此時(shí)返回值應(yīng)該為1
分治+歸并獲取葉子節(jié)點(diǎn)的個(gè)數(shù)
int getLeavesNode(Tree *root) {if (root == NULL) {return 0;} else {if (root -> left == NULL && root ->right == NULL) {return 1;}return getLeavesNode(root -> left) + getLeavesNode(root -> right);}
}
獲取樹(shù)的高度
樹(shù)的高度為左右子節(jié)點(diǎn)的 層數(shù)較大的一個(gè)數(shù)值
實(shí)現(xiàn)過(guò)程如下:
int heightTree(Tree *root) {int height = 0;if (root == NULL) {return 0;} else {int l_height = heightTree(root -> left);int r_height = heightTree(root -> right);height = l_height > r_height? l_height +1 :r_height+1;}return height;
}
測(cè)試代碼
#include <iostream>
#include <stack>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>using namespace std;typedef struct tree
{char data;struct tree *left;struct tree *right;
}Tree,*TreeNode;/*創(chuàng)建二叉樹(shù)*/
void createTree(TreeNode *root) {char val = 0;cin >> val;if (val == '*') {(*root) = NULL;} else {(*root) = (Tree *)malloc(sizeof(tree));if ((*root) == NULL) {cout << "create node failed " << endl;exit(-1);} else {(*root)->data = val;createTree(&(*root)->left);createTree(&(*root)->right);}}
}/*遞歸先序遍歷*/
void preOrder(Tree *root) {if (root == NULL) {return;}cout << root->data;preOrder(root->left);preOrder(root->right);
}/*非遞歸先序遍歷*/
void preOrderNoRecur(Tree *root) {if (root == NULL) {return;}stack<TreeNode> s;Tree *p = root;while(!s.empty() || p) {while(p) {cout << p ->data;s.push(p);p = p->left;}while(!s.empty()) {p = s.top();s.pop();p = p -> right;}}cout << endl;}/*遞歸中序遍歷*/
void inorder(Tree *root) {if (root == NULL) {return;}inorder(root -> left);cout << root -> data;inorder(root -> right);
}/*非遞歸中序遍歷*/
void inorderNoRecur(Tree *root) {if (root == NULL) {return;}stack<TreeNode> s;Tree *p = root;while(!s.empty() || p) {while(p) {s.push(p);p = p ->left;}while(!s.empty()) {p = s.top();cout << p->data;s.pop();p = p->right;}}cout << endl;
}/*遞歸后序遍歷*/
void lastorder(Tree *root) {if (root == NULL) {return;}lastorder(root -> left);lastorder(root -> right);cout << root -> data;
}void lastorderNoRecur(Tree *root) {if (root == NULL) {return;}stack<TreeNode> s;Tree *p = root;Tree *lastvisit = NULL;while(p) {s.push(p);p = p ->left;}while(!s.empty()) {p = s.top();s.pop();/*右節(jié)點(diǎn)已經(jīng)為空或者已經(jīng)訪(fǎng)問(wèn)過(guò),那么認(rèn)為右節(jié)點(diǎn)已經(jīng)訪(fǎng)問(wèn)完,可以訪(fǎng)問(wèn)根節(jié)點(diǎn)了*/if (p -> right == NULL || p ->right == lastvisit) {cout << p->data;lastvisit = p;} else {//否則,將右節(jié)點(diǎn)以及右節(jié)點(diǎn)的子節(jié)點(diǎn)入棧從而繼續(xù)訪(fǎng)問(wèn)s.push(p);p = p -> right;while(p) {s.push(p);p = p -> left;}}}cout << endl;
}int getLeavesNode(Tree *root) {if (root == NULL) {return 0;} else {if (root -> left == NULL && root ->right == NULL) {return 1;}return getLeavesNode(root -> left) + getLeavesNode(root -> right);}
}int heightTree(Tree *root) {int height = 0;if (root == NULL) {return 0;} else {int l_height = heightTree(root -> left);int r_height = heightTree(root -> right);height = l_height > r_height? l_height +1 :r_height+1;}return height;
}int main(int argc, char const *argv[])
{/* code */TreeNode root;cout << "construct the tree " << endl;createTree(&root);cout << "previous order recursion " << endl;preOrder(root);cout << "\nprevious order no recursion " << endl;preOrderNoRecur(root);cout << "inorder recursion " << endl;inorder(root);cout << "\ninorder no recursion " << endl;inorderNoRecur(root);cout << "lastorder recursion " << endl;lastorder(root);cout << "\nlastorder no recursion " << endl;lastorderNoRecur(root);cout << "height of the tree is " << heightTree(root) << endl;cout << "num leaves of the tree is " << getLeavesNode(root) << endl;return 0;
}
輸出如下:
#輸入
construct the tree
ABD***CE**FG***
#輸出
previous order recursion
ABDCEFG
previous order no recursion
ABDCEFG
inorder recursion
DBAECGF
inorder no recursion
DBAECGF
lastorder recursion
DBEGFCA
lastorder no recursion
DBEGFCA
height of the tree is 4
num leaves of the tree is 3
總結(jié)
以上是生活随笔為你收集整理的二叉树(C++):创建,前中后序遍历(递归+非递归),获取叶子节点个数,获取树的高度的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 大家知道那有鸬鹚(鱼鹰或是水老鸦)卖,我
- 下一篇: 《春雪》第七句是什么