文章目录

  • ​​1.二叉树遍历的问题提出​​
  • ​​2.先序遍历算法​​
  • ​​3.中序遍历算法​​
  • ​​3.后序遍历算法​​
  • ​​4.二叉树的层次遍历​​
  • ​​5.二叉树遍历算法的应用举例​​

1.二叉树遍历的问题提出

  • 顺着某一条搜索路径巡访二叉树中的结点,使得每个结点均被访问一次,而且仅被访问一次。
  • 常见的遍历方式有:
    (1)递归遍历
    (2)层次遍历
    (3)非递归遍历:使用堆栈

2.先序遍历算法

  • 若二叉树非空,则,
    (1)访问根结点;
    (2)先序遍历左子树:递归式
    (3)先序遍历右子树:递归式
  • 二叉树先序遍历算法的实现
typedef struct BiTreeNode
{
Datatype data;
struct BiTreeNode *lchild, *rchild, *parent;
}BiTreeNode, *BiTree;


void PreOrder(BiTree bt)
{
if (bt!=NULL)//如果bt为空,结束
{
visit(br->data);//访问根节点
PreOrder(bt->lchild);//递归调用:先序遍历左子树
PreOrder(bt->rchild);//递归调用:先序遍历右子树
}
}
  • 二叉树的递归遍历 | 先序遍历DLR:即根左右,根左子树、右子树

3.中序遍历算法

  • 若二叉树非空,则,
    (1)中序遍历左子树;
    (2)访问根结点;
    (3)中序遍历右子树。
  • 二叉树中序遍历算法的实现
typedef struct BiTreeNode
{
Datatype data;
struct BiTreeNode *lchild, *rchild, *parent;
}BiTreeNode, *BiTree;



void Inorder(BiTree bt)
{
if (bt!=NULL)//如果bt为空,结束
{
InOrder(bt->lchild);//递归调用:中序遍历左子树
visit(bt->data);//访问根节点
InOrder(bt->rchild);//递归调用:中序遍历右子树
}
}
  • 二叉树的递归遍历 | 中序遍历DLR:即左根右,即:左子树,根,右子树

3.后序遍历算法

  • 若二叉树非空,则,
    (1)后序遍历左子树;
    (2)后序遍历右子树;
    (3)访问根结点。
  • 二叉树后序遍历算法的实现
typedef struct BiTreeNode
{
Datatype data;
struct BiTreeNode *lchild, *rchild, *parent;
}BiTreeNode, *BiTree;

void LaOrder(BiTree bt)
{
if(bt!=NULL)//如果bt为空,结束
{
LaOrder(bt->lchild);//递归调用:后序遍历左子树
LaOrer(bt->rchild);//递归调用:后序遍历右子树
visit(bt->data);//访问根节点
}
}
  • 二叉树的递归遍历 | 后序遍历DLR:即左根右,即:左右根,即左子树,右子树,根

4.二叉树的层次遍历

  • 思想:从根节点点开始,从上到下,从左到右逐层的进行遍历
  • 二叉树层次遍历算法的实现
typedef struct BiTreeNode
{
Datatype data;
struct BiTreeNode *lchild, *rchild, *parent;
}BiTreeNode, *BiTree;

void LevelOrder(Bitree bt)
{
BitTreeNode Queue[MAXNODE];//定义队列
int front,rear;
if(bt==NULL)//空二叉树,遍历结束
return;
front=-1;
rear=0;
Queue[rear]=bt;//根节点入队列
while(rear!=front)//队列不为空,继续遍历,否则遍历结束
{
front++;//出队
visit(Queue[front]->data);//访问刚出队的元素
if (Queue[front]->lchild!=NULL)//如果有左孩子,左孩子入队
{
rear++;
Queue[rear]=Queue[front]->lchild;
}
if(Queue[front]->rchild!=NULL)//如果有右孩子,右孩子入队
{
rear++;
Queue[rear]=Queue[front]->rchild;
}
}
}

5.二叉树遍历算法的应用举例

(1)建立二叉树(先序和中序,中序和后序也可以建立一颗二叉树)
(2)统计二叉树中叶子结点的个数(先序遍历)
(3)求二叉树的深度(后序遍历)

  • (1)建立二叉树(先序和中序)
  • (4.2)树与二叉树之二叉树的遍历_二叉树

  • 利用先序序列和中序序列确定一颗二叉树
  • (4.2)树与二叉树之二叉树的遍历_二叉树_02

  • 利用先序和后序构建二叉树的算法:先理解上面的eg,再看下面的代码就懂了
  • (4.2)树与二叉树之二叉树的遍历_结点_03

typedef struct BiTreeNode
{
Datatype data;
struct BiTreeNode *lchild, *rchild, *parent;
}BiTreeNode, *BiTree;


void BiTree(char preord[],char inord[],int n, BiTree root)
{
//n为二叉树节点的个数,建立的二叉树放在root中
if (n<=0)
root=NULL;
else
PreInOrd(preord,inord,1,n,1,n,&root);
}

//preord数组存放先序遍历的元素,inord存放的是中序遍历的数组元素
void PreInOrd(char preord[], char inord[], int i, int j, int k, int h, BiTree *t)/注意这里是双指针
{
//先序序列从i到j,中序序列从k到h,建立一颗二叉树放在t中
int m;
(*t)=new BiNode;
(*t)->data=preord[i];//二叉树的根
m=k;
while(inord[m]!=preord[i])//在中序序列中定位树根
m++;
//递归调用建立左子树
if (m==k)//左子树为空
(*t)->lchild=NULL;
else
PreInOrd(preord, inord, i+1,i+m-k,k,m-1,&((*t)->lchild));//结合上面的eg会更好的理解

//递归调用建立右子树
if (m==h)//右子树为空
(*t)->rchild=NULL;
else
PreInOrd(preord, inord, i+m-k+1,j,m+1,h,&((*t)->rchild));//结合上面的eg会更好的理解
}
  • (2)二叉树中叶结点统计
    先序(中序或后序)遍历二叉树,在遍历过程中查找叶结点,将算法中“访问结点”的操作改为: 判叶结点。
    思路:使用分治思想,因为叶子节点的左右节点为空,只有根;
    所以:左子树的叶子节点的个数+右子树的叶子节点的个数
  • 代码如下:
typedef struct BiTreeNode
{
Datatype data;
struct BiTreeNode *lchild, *rchild, *parent;
}BiTreeNode, *BiTree;

int CountLeaf(BiTree T)
{
if (T=NULL)
return 0;
if (T->lchild==NULL && T->rchild==NULL)
return 1;
else
CountLeaf(T-lchild)+CountLeaf(T->rchild);
}
  • (3)二叉树的深度
    空树:深度=0
    左右子树为空:深度=1
    其它 :深度=1+max(左子树深度,右子树深度),这里的1代表根节点
    思想:利用分治思想,递归
  • 代码如下:
typedef struct BiTreeNode
{
Datatype data;
struct BiTreeNode *lchild, *rchild, *parent;
}BiTreeNode, *BiTree;

int BitreeDepth(BiTree bt)
{
if (bt==NULL)//空树,深度为0
return 0;
if (bt->lchild==NULL && bt->rchild==NULL)
return 1;//叶子节点,深度为1
depthL=BitreeDepth(bt->lchild);//左子树深度
depthR=BitreeDepth(bt->rchild);//右子树深度
return 1+max(depthL, depthR);//整颗二叉树的深度为:左子树和右子树中最大的深度加1
}