-
二叉树简述
1、第i层至多有2的 i -1次方个结点;
2、深度为k的二叉树至多有2^(k) -1个结点;
3、叶子结点个数为n,双结点个数为m,则 n = m + 1
4、递归遍历方式代码简单,效率低;非递归遍历方式代码较复杂,效率高
5、层序遍历需要借助(queue)实现,前、中、后序遍历需借助栈(stack)实现。
-
节点定义
typedef struct Node_t{
struct Node_t * left;
struct Node_t * right;
int value;
Node_t(int a):value(a),left(NULL),right(NULL)
{
}
}Node_t;
-
先(前)序遍历。
访问顺序:value——>左子树——>右子树
1、递归算法
void preOrderRecursion(Node_t *root){
if(root){
visit(root);
preOrderRecursion(root->left);
preOrderRecursion(root->right);
}
}
2、非递归算法
思路:root节点先进栈,访问栈顶元素,访问后出栈同时,右节点先入栈,左节点再入栈。
void preOrder(Node_t *root){
if(!root){
return;
}
stack<Node_t *> S;
Node_t *p = root;
S.push(root);
while(!S.empty()){
p = S.top();
visit(p);
S.pop();
if(p->right){
S.push(p->right);
}
if(p->left){
S.push(p->left);
}
}
}
-
中序遍历
访问顺序:左子树——>value——>右子树
1、递归算法
void midOrderRecursion(Node_t *root){
if(root){
midOrderRecursion(root->left);
visit(root);
midOrderRecursion(root->right);
}
}
2、非递归算法
思路:root节点先进栈,循环将左子树入栈,开始访问栈顶元素,访问后出栈同时将栈顶元素的右子树入栈。
void midOrder(Node_t *root){
stack<Node_t *> S;
S.push(root);
Node_t *p = root;
while(!S.empty()){
p = S.top();
while(p){
S.push(p->left);
p = p->left;
}
S.pop(); //pop out the nullptr
if(!S.empty()){
p = S.top();
visit(p);
S.pop();
S.push(p->right);//push its right child into the stack
}
}
}
-
后序遍历
访问顺序:左子树——>右子树——>value
1、递归算法
void postOrderRecursion(Node_t *root){
if(root){
postOrderRecursion(root->left);
postOrderRecursion(root->right);
visit(root);
}
}
2、非递归算法
思路:循环将左子树入栈,开始检查栈顶元素的右子树,如果右子树为空或者右子树已被访问,即可访问当前栈顶元素。
如果之前访问过的节点last恰为该节点的右节点,说明其右子树已经访问完,应该访问该栈顶元素。
void postOrder(Node_t *root){
Node_t *last = nullptr;
Node_t *p = root;
stack<Node_t *> S;
while( p || !S.empty()){
while(p){
S.push(p);
p = p->left;
}
p = S.top();
if(p->right && p->right != last){
p = p->right;
}else{
visit(p);
S.pop();
last = p;
p = nullptr; //p needs to be updated to null for next loop
}
}
}
-
层序遍历
思想:需要借助queue来对节点进行缓存,先进队列的节点需要先离开
void levelOrder(Node_t *root){
if(!root){
return;
}
queue<Node_t *> Q;
Node_t *p = nullptr;
Q.push(root);
while(!Q.empty()){
p = Q.front();
Q.pop();
visit(p);
if(p->left){
Q.push(p->left);
}
if(p->right){
Q.push(p->right);
}
}
}