先序遍历按照根结点->左孩子->右孩子
的顺序进行访问。
void preOrder1(BiTree *root)
{
if(root != NULL)
{
cout<<root->key<<" ";
preOrder1(root->left);
preOrder1(root->right);
}
}
根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问完其左子树时,再访问它的右子树。因此其处理过程如下:
对于任一结点P:
1)访问结点P,并将结点P入栈;
2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈
顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当
前的结点P;
3)直到P为NULL并且栈为空,则遍历结束。
代码:
void preOrder2(BiTree *root)
{
stack s;
BiTree *p=root;
while(p != NULL || !s.empty())
{
while(p != NULL)
{
cout<key<<" ";//(1)先访问根节点
s.push(p);
p=p->left;//(2)左孩子作为根节点,直至为空
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->right;//(3)右孩子作为根节点
}
}
}
中序遍历按照左孩子-根结点-右孩子
的顺序进行访问。
void inOrder1(BiTree *root)
{
if(root != NULL)
{
inOrder1(root->left);
cout<<root->key<<" ";
inOrder1(root->right);
}
}
对于任一结点P,
1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P
再进行相同的处理;
2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当
前的P置为栈顶结点的右孩子;
3)直到P为NULL并且栈为空则遍历结束
代码:
void inOrder2(BiTree *root)
{
stack s;
BiTree *p=root;
while(p != NULL || !s.empty())
{
while(p != NULL)
{
s.push(p);
p=p->left;//(1)左
}
if(!s.empty())
{
p=s.top();
cout<key<<" ";//(2)中。跟preOrder2的区别是该处换了地方
s.pop();
p=p->right;//(3)右
}
}
}
后序遍历按照左孩子-右孩子-根结点
的顺序进行访问。
void postOrder1(BiTree *root)
{
if(root != NULL)
{
postOrder1(root->left);
postOrder1(root->right);
cout<<root->key<<" ";
}
}
要保证根结点在左孩子和右孩子访问之后才能访问,因此:
1)对于任一结点P,先将其入栈。
2)如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩
子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。
3)若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取
栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被
访问。
代码:
void postOrder2(BiTree *root)
{
stack<BiTree*> s;
BiTree *p=root;//当前结点
BiTree *pre=NULL;//前一次访问的结点 !!!
s.push(p);
while(!s.empty())
{
p=s.top();
if((p->left==NULL && p->right==NULL) ||
pre != NULL &&(pre==p->left || pre==p->right))
{//如果当前结点没有孩子结点或者孩子节点都已被访问过
cout<<p->key<<" ";
s.pop();
pre=p;
}
else
{//否则,右孩子,左孩子,依次入栈
if(p->right)
s.push(p->right);
if(p->left)
s.push(p->left);
}
}
}
分层遍历该二叉树,即从上到下按层次访问该二叉树(每一层可单独输出一行),每一层要求访问的顺序为从左到右。
利用图的广度优先搜索,外加一个queue实现。
遍历时直接一行输出,不分行打印
void layerOrder1(BiTree *root)
{
if(root==NULL) return;
queue q;
BiTree *p=root;
q.push(p);
while(!q.empty())
{
p=q.front();
cout<key<<" ";
q.pop();
if(p->left)
q.push(p->left);
if(p->right)
q.push(p->right);
}
}
遍历时按二叉树的层次分行输出
我们可以在遍历当前层的时候,保存下一层的节点数,只需要每次插入一个节点的时候childNum++即可,这样我们就知道下一层有几个节点了,然后将childNum赋值给parentNum,开始新的一层遍历,从队列中取出parentNum个节点以后,也就知道这一层遍历完了。
由于这是二叉树,所以一开始的时候parentNum = 1, childNum = 0。
void layerOrder2(BiTree *root)
{
if(root==NULL) return;
int parentNum=1, childNum=0;//在根节点时parent只有一个,child为0
queue q;
BiTree *p=root;
q.push(p);
while(!q.empty())
{
p=q.front();
cout<key<<" ";
q.pop();
if(p->left)
{
q.push(p->left);
childNum++;
}
if(p->right)
{
q.push(p->right);
childNum++;
}
parentNum--;
if(parentNum==0)
{
parentNum=childNum;//更新下一层parent数
childNum=0;//更新下一层child数
cout<//换行
}
}
}
递归先序遍历:
1 2 4 5 3 6 8 7
非递归先序遍历:
1 2 4 5 3 6 8 7
递归中序遍历:
4 2 5 1 6 8 3 7
非递归中序遍历:
4 2 5 1 6 8 3 7
递归后序遍历:
4 5 2 8 6 7 3 1
非递归后序遍历:
4 5 2 8 6 7 3 1
层次遍历方法一:
1 2 3 4 5 6 7 8
层次遍历方法二:
1
2 3
4 5 6 7
8
Process returned 0 (0x0) execution time : 0.465 s
Press any key to continue.
代码:
#include
#include
#include
using namespace std;
typedef struct BinaryTreeNode
{
int key;
struct BinaryTreeNode *left;
struct BinaryTreeNode *right;
}BTNode, BiTree;
//创建二叉树节点
BTNode *CreateBTNode(int key)
{
BTNode *node = new BTNode;
node->key = key;
node->left = node->right = NULL;
return node;
}
void preOrder1(BiTree *root)
{
if(root != NULL)
{
cout<key<<" ";
preOrder1(root->left);
preOrder1(root->right);
}
}
void preOrder2(BiTree *root)
{
stack s;
BiTree *p=root;
while(p != NULL || !s.empty())
{
while(p != NULL)
{
cout<key<<" ";//(1)先访问根节点
s.push(p);
p=p->left;//(2)左孩子作为根节点,直至为空
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->right;//(3)右孩子作为根节点
}
}
}
void inOrder1(BiTree *root)
{
if(root != NULL)
{
inOrder1(root->left);
cout<key<<" ";
inOrder1(root->right);
}
}
void inOrder2(BiTree *root)
{
stack s;
BiTree *p=root;
while(p != NULL || !s.empty())
{
while(p != NULL)
{
s.push(p);
p=p->left;//(1)左
}
if(!s.empty())
{
p=s.top();
cout<key<<" ";//(2)中。跟preOrder2的区别是该处换了地方
s.pop();
p=p->right;//(3)右
}
}
}
void postOrder1(BiTree *root)
{
if(root != NULL)
{
postOrder1(root->left);
postOrder1(root->right);
cout<key<<" ";
}
}
void postOrder2(BiTree *root)
{
stack s;
BiTree *p=root;//当前结点
BiTree *pre=NULL;//前一次访问的结点 !!!
s.push(p);
while(!s.empty())
{
p=s.top();
if((p->left==NULL && p->right==NULL) ||
pre != NULL &&(pre==p->left || pre==p->right))
{//如果当前结点没有孩子结点或者孩子节点都已被访问过
cout<key<<" ";
s.pop();
pre=p;
}
else
{//否则,右孩子,左孩子,依次入栈
if(p->right)
s.push(p->right);
if(p->left)
s.push(p->left);
}
}
}
void layerOrder1(BiTree *root)
{
if(root==NULL) return;
queue q;
BiTree *p=root;
q.push(p);
while(!q.empty())
{
p=q.front();
cout<key<<" ";
q.pop();
if(p->left)
q.push(p->left);
if(p->right)
q.push(p->right);
}
}
void layerOrder2(BiTree *root)
{
if(root==NULL) return;
int parentNum=1, childNum=0;//在根节点时parent只有一个,child为0
queue q;
BiTree *p=root;
q.push(p);
while(!q.empty())
{
p=q.front();
cout<key<<" ";
q.pop();
if(p->left)
{
q.push(p->left);
childNum++;
}
if(p->right)
{
q.push(p->right);
childNum++;
}
parentNum--;
if(parentNum==0)
{
parentNum=childNum;//更新下一层parent数
childNum=0;//更新下一层child数
cout<int main()
{
BTNode *root = CreateBTNode(1);
root->left = CreateBTNode(2);
root->right = CreateBTNode(3);
root->left->left = CreateBTNode(4);
root->left->right = CreateBTNode(5);
root->right->left = CreateBTNode(6);
root->right->right = CreateBTNode(7);
root->right->left->right = CreateBTNode(8);
cout<<"递归先序遍历:"<cout<cout<<"非递归先序遍历:"<cout<cout<<"递归中序遍历:"<cout<cout<<"非递归中序遍历:"<cout<cout<<"递归后序遍历:"<cout<cout<<"非递归后序遍历:"<cout<cout<<"层次遍历方法一:"<cout<cout<<"层次遍历方法二:"<return 0;
}
若一棵二叉树为空,则它的深度为0,否则它的深度等于左子树和右子树中的最大深度加1. 设nLeft为左子树的深度,nRight为右子树的深度,
则二叉树的深度为:max(nLeft , nRight)+1.
//树的深度
int TreeDepth(BTree* root)
{
int nLeft, nRight;
if(root == NULL)//必不可少的条件,递归的出口
return 0;
nLeft = TreeDepth(root->lchild);
nRight = TreeDepth(root->rchild);
return (nLeft > nRight) ? (nLeft + 1):(nRight + 1);
}
若存在,则由x带回完整值并返回真,否则返回假。
该算法类似于前序遍历,若树为空则返回false结束递归,若树根结点的值就等于x的值,则把结点值赋给x后返回true结束递归,否则先向左子树查找,若找到则返回true结束递归,否则再向右子树查找,若找到则返回true结束递归,若左,右子树均未找到则返回false结束递归。
bool FindBTree(BTreeNode *BT , ElemType &x)
{
if(BT == NULL) //树为空返回假
return false;
if(BT->data == x) //树根结点的值等于x则由x带回结点值并返回真
{
x = BT->data;
return true;
}
else
{
//向左子树查找,若成功则继续返回真
if(FindBTree(BT->left , x))
return true;
//向右子树查找,若成功则继续返回真
if(FindBTree(BT->right , x))
return true;
//左,右子树查找均失败则返回假
return false;
}
}
结果由函数返回。
此算法也是一个递归过程,若树为空则返回0结束递归,若树根结点的值等于x的值则返回左、右两棵子树中等于x结点的个数加1,否则只应返回左、右两棵子树中等于x结点的个数。
int CountX(BTreeNode *BT , ElemType &x)
{
if(BT == NULL) //空树返回0
return 0;
if(BT->data == x)
return CountX(BT->left , x)+CountX(BT->right , x) + 1;
//返回1加上两子树中的x结点数
else
return CountX(BT->left , x)+CountX(BT->right , x);
//返回两子树中的x结点数
}
int NodeLevel(BTreeNode *BT , ElemType &x)
{
//空树的层号为0
if(BT == NULL)
return 0;
//根结点的层号为1
if(BT->data == x)
return 1;
else
{
//求出x在左子树中的层号,返回该层号加1
int c1 = NodeLevel(BT->left , x);
if(c1 >= 1)
return c1+1;
//求出x在右子树中的层号,返回该层号加1
int c2 = NodeLevel(BT->right , x);
if(c2 >= 1)
return c2+1;
//在左、右子树中都不存在x结点则返回0
else
return 0;
}
}
ElemType MaxValue(BTreeNode *BT)
{
if(BT == NULL)
return 0; //空树返回0
ElemType k1 , k2;
k1 = MaxValue(BT->left); //求出左子树中的最大值
k2 = MaxValue(BT->right); //求出右子树中的最大值
if(k1 < k2)
k1 = k2; //两子树的最大值赋给k1
if(k1 > BT->data)
return k1;
else
return BT->data;
}
int BTreeCount(BTreeNode *BT)
{
if(BT == NULL)
return 0;
else
return BTreeCount(BT->left) + BTreeCount(BT->right) + 1;
}
int BTreeLeafCount(BTreeNode *BT)
{
if(BT == NULL)
return 0;
if(BT->left == NULL && BT->right == NULL)
return 1;
else
return BTreeLeafCount(BT->left) + BTreeLeafCount(BT->right);
}
参考:
http://blog.csdn.net/lalor/article/details/7626854
http://www.cnblogs.com/heyonggang/p/3399464.html
http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html