红黑树也是二叉树,这里只是说明对树的遍历访问。插入、 查找、 删除 等操作参看红黑树那里
1、深度优先搜索:每种都有递归和迭代两种实现(迭代需要借助stack)
前序遍历:10,6,4,8,14,12,16
中序遍历:4,6,8,10,12,14,16(如果是二叉排序树就是输出排序结果了哈)
后序遍历:4,8,6,12,16,14,10
a.递归实现
递归实现相当简单:
void preOrder(BTree *tree)
{
if(tree == NULL)
return;
//operator~~(前中后序不同就是此operator所在位置不同)
if(tree->left)
preOrder(tree->left);
if(tree->right)
preOrder(tree->right);
}
b.迭代实现
重点说下迭代实现:(有左子树就一直访问下去,直到没了再看右子树。感觉右子树都是挂在左子树上的啊。。。)
前序
void preOrder2(BTree *root) //非递归前序遍历,按前序遍历走一遍就能理解他的思路了
{
stack<BTree *> s;
BTree *p=root;
while(p!=NULL||!s.empty()) // 注意 p==NULL 时并不会退出while
{
while(p!=NULL) //左子树非空时将一直遍历下去
{
cout<<p->data<<" ";
s.push(p);
p=p->lchild;
} //最后p肯定是一个叶子节点了(NULL)才退出while
if(!s.empty()) //
{
p=s.top();
s.pop();
p=p->rchild;
}
}
}
中序
void inOrder2(BTree *root) //非递归中序遍历
{
stack<BTree*> s;
BTree *p=root;
while(p!=NULL||!s.empty())
{
while(p!=NULL)
{
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
cout<<p->data<<" ";
s.pop();
p=p->rchild;
}
}
}
后序
//非递归后序遍历相对复杂,可以沿承上面的做法,那就要在拿到s.top时候看是不是第一次处于top,如果是,那说明右子树还没有被访问呢,那就只是置flag,
//直接把右边孩子继续push。当第二次位于栈顶的时候就是该pop并访问此节点的时候。(这种做法需要在每个node里面加个flag)
void postOrder2(BTree *root) //非递归后序遍历
{
stack<BTNode*> s;
BTree *p=root;
BTNode *temp; //这是新定义的node,多加了个flag
while(p!=NULL||!s.empty())
{
while(p!=NULL) //沿左子树一直往下搜索,直至出现没有左子树的结点
{
BTNode *btn=(BTNode *)malloc(sizeof(BTNode));
btn->btnode=p;
btn->isFirst=true;
s.push(btn);
p=p->lchild;
}
if(!s.empty())
{
temp=s.top();
s.pop();
if(temp->isFirst==true) //表示是第一次出现在栈顶
{
temp->isFirst=false;
s.push(temp);
p=temp->btnode->rchild;
}
else //第二次出现在栈顶
{
cout<<temp->btnode->data<<" ";
p=NULL;
}
}
}
}
//还有一种做法: http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html
void postOrder2(BinTree *root) //非递归后序遍历
{
stack<BinTree*> s;
BinTree *cur; //当前结点
BinTree *pre=NULL; //前一次访问的结点
s.push(root); //先把root入栈
while(!s.empty())
{
cur=s.top();
if( (cur->lchild==NULL && cur->rchild==NULL)|| //当前节点为叶子节点
(pre!=NULL && (pre==cur->lchild||pre==cur->rchild))) //上一个访问的节点正是cur的右孩子,或者没有右孩子那就是是cur的左孩子。我感觉这里写的有问题
{
cout<<cur->data<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过
s.pop();
pre=cur; //按照这个pop的顺序,pre 应该是 cur 的孩子
}
else
{
if(cur->rchild!=NULL)
s.push(cur->rchild); //注意这里先入栈的是cur的右孩子(保证pop的时候先出来的是left)
if(cur->lchild!=NULL)
s.push(cur->lchild);
}
}
}
2、宽度优先搜索
10,6,14,4,8,12,16。实现的话需要借助queue:
比如上面,A入队,queue<--A
A出队,并将A的所有child入队(BC入队),queue<--B<--C
B出队,并将B的所有child入队(DE入队),queue<--C<--D<--E
………………………
由二叉树的遍历引申出 求二叉树的深度,
int GetTreeDeep(BinTree BT) //类似后序遍历
{
int deep=0; //叶子节点深度为0
if(BT)
{ //左右子树的深度,二者较大者加1即是树的深度
int lchilddeep = GetTreeDeep(BT->lchild);
int rchilddeep = GetTreeDeep(BT->rchild);
deep = (lchilddeep>=rchilddeep)? lchilddeep+1 : rchilddeep+1;
}
return deep;
}