1.先序、中序、后序遍历
void preorder(node *root)//先序遍历,中左右
{
if(root==NULL) return;
printf("%d\n",root->data);//访问根结点root,如这里的输出数据域
preorder(root->lchild);
preorder(root->rchild);
}
void inorder(node *root)//中序遍历,左中右
{
if(root==NULL) return;
inorder(root->lchild);
printf("%d\n",root->data);//访问根结点root,如这里的输出数据域
inorder(root->rchild);
}
void postorder(node *root)//后序遍历,左右中
{
if(root==NULL) return;
postorder(root->lchild);
postorder(root->rchild);
printf("%d\n",root->data);//访问根结点root,如这里的输出数据域
}
易知:由先序和后序可得到根结点(排在最前面或者最后面的结点),如欲得到整棵二叉树,则需要已知先序or后序or层次+中序,因为已知根结点,可根据中序“左中右”,得到左右子树,并对左右子树递归重复上述过程,得到一棵完整的二叉树(层次遍历加中序遍历后面讲)
2.层序遍历
①将根结点加入队列q
②取出队首结点访问它
③如果有左孩子,将左孩子入队
④如果有右孩子,将右孩子入队
⑤返回②,直至队空
void layerorder(node *root)
{
queue<node*> q;
q.push(root);
while(!q.empty())
{
node *now=q.front();
printf("%d\n",now->data);
q.pop();
if(now->lchild!=NULL) q.push(now->lchild);
if(now->rchild!=NULL) q.push(now->rchild);
}
}
注意使用的队列是node*型,因为队列queue中存储的实际上是原元素的副本,对副本进行修改不会影响原元素本身,因此这里为了实现对队首元素的修改,采用了node*通过访问地址的方式修改原元素
另外层次遍历中经常要求计算每个结点所在的层,所以需要在二叉链表的结构体定义中加一个记录layer的变量
struct node
{
typename data;
node *rchild,*lchild;
int layer;
};
注意层数是根结点为1,高度是最底层为1,树的高度和层数是一样的(因为树的高度为最大的结点高度,层数同理),但对于具体某一个结点,高度和层数不一定相等
void layerorder(node *root)
{
queue<node*> q;
q.push(root);
root->layer=1;
while(!q.empty())
{
node *now=q.front();
printf("%d\n",now->data);
q.pop();
if(now->lchild!=NULL)
{
now->lchild->layer=now->layer+1;
q.push(now->lchild);
}
if(now->rchild!=NULL)
{
now->rchild->layer=now->layer+1
q.push(now->rchild);
}
}
}