数据结构—基础知识(11):二叉树的遍历

数据结构---基础知识(11):二叉树的遍历

二叉树的遍历

二叉树的遍历是指按某条搜索路径访问树中每个结点,使得每个结点均被访问一次,而且仅被访问一次。由于二叉树是一种非线性结构,每个结点都可能有两棵子树,因而需要寻找一种规律,以便使二叉树上的结点能排列在一个线性队列上,进而便于遍历。

由二叉树的递归定义可知,遍历一棵二叉树便要决定对根结点N、左子树L和右子树R的访问顺序。按照先遍历左子树再遍历右子树的原则,常见的遍历次序有先序(NLR)、中序(LNR)和后序(LRN)三种遍历算法,其中"序"指的是根结点在何时被访问。

先序遍历:ABCDEFGH

中序遍历:BDCEAFHG

后序遍历:DECBHGFA

先序遍历

先序遍历的操作过程如下:

若二叉树为空则什么都不做;否则,①访问根节点;②先序遍历左子树;③先序遍历右子树。

对应的递归算法:

c 复制代码
void PreOrder(BinTree T)
{//先序遍历的递归算法
    if(T!=NULL)
    {
        visit(T);//访问根结点
        PreOrder(T->lchild);//递归遍历左子树
        PreOrder(T->rchild);//递归遍历右子树
    }
}

先序遍历的非递归算法:

c 复制代码
void PreOrder2(BinTree T)
{//先序遍历的非递归算法
    InitStack(S);BiTree p=T;//初始化栈S;p是遍历指针
    while(p||!IsEmpty(S))//栈不空或p不空时循环
    {
        if(p){//一路向左
            visit(p);Push(S,p);//访问当前结点,并入栈
            p=p->lchild;//左孩子不空,一直向左走
        }
        else{//出栈,并转向出栈结点的右子树
            Pop(S,p);//栈顶元素出栈
            p=p->rchild;//向右子树走,p赋值为当前结点的右子树
        }//返回while循环继续进入if-else语句
    }
}

中序遍历

中序遍历的操作过程如下:

若二叉树为空则什么都不做;否则,①先序遍历左子树;②访问根节点;③先序遍历右子树。

对应的递归算法:

c 复制代码
void InOrder(BinTree T)
{//中序遍历的递归算法
    if(T!=NULL)
    {
        InOrder(T->lchild);//递归遍历左子树
        visit(T);//访问根结点
        InOrder(T->rchild);//递归遍历右子树
    }
}

中序非递归遍历

c 复制代码
void InOrder2(BiTree T)
{
    InitStack(S); BiTree p=T;//初始化栈S;p是遍历指针
    while(p||!IsEmpty(S))//栈不空或p不空时循环
    {
        if(p){//一路向左
            Push(S,p);//当前结点入栈
            p=p->1child;//左孩子不空,一直向左走
        } 
        else{//出栈,并转向出栈结点的右子树
            Pop(S,p);visit(p);//栈顶元素出栈,访问出栈结点
            p=p->rchild;//向右子树走,p赋值为当前结点的右孩子
        }//返回 while 循环继续进入if-else语句
    }
}

后序遍历

后序遍历的操作过程如下:

若二叉树为空则什么都不做;否则,①先序遍历左子树;②先序遍历右子树;③访问根节点。

对应的递归算法:

c 复制代码
void PostOrder(BinTree T)
{//后序遍历的递归算法
    if(T!=NULL)
    {
        PostOrder(T->lchild);//递归遍历左子树
        PostOrder(T->rchild);//递归遍历右子树
        visit(T);//访问根结点
    }
}

后序遍历的非递归算法:

c 复制代码
void PostOrder (BiTree T)
{
    InitStack(S);
    BiTNode *p=T;
    BiTNode *r=NULL;
    while(p||!IsEmpty(S))
    {
        if(p){//走到最左边
            push(S,p);
            p=p->lchild;
        }
        else{//向右
            GetTop(S,p);//读栈顶结点(非出栈)
            if(p->rchild&&p->rchild!=r)//若右子树存在,且未被访问过
                p=p->rchild;//转向右
            else{//否则,弹出结点并访问
                pop(S,p);//将结点弹出
                visit(p->data);//访问该结点
                r=p;//记录最近访问过的结点
                p=NULL;//结点访问完后,重置p指针
            }
        }//else
    }//while
}
相关推荐
雾里看山1 小时前
顺序表VS单链表VS带头双向循环链表
数据结构·链表
DKPT1 小时前
Java桥接模式实现方式与测试方法
java·笔记·学习·设计模式·桥接模式
努力的小雨3 小时前
点我!1分钱获取你的专属表白网页,浪漫由大模型代运营
经验分享·ai智能
巴伦是只猫3 小时前
【机器学习笔记Ⅰ】13 正则化代价函数
人工智能·笔记·机器学习
好好研究4 小时前
学习栈和队列的插入和删除操作
数据结构·学习
新中地GIS开发老师5 小时前
新发布:26考研院校和专业大纲
学习·考研·arcgis·大学生·遥感·gis开发·地理信息科学
Luna-player6 小时前
黑布淡入淡出效果
经验分享·游戏
挺菜的6 小时前
【算法刷题记录(简单题)003】统计大写字母个数(java代码实现)
java·数据结构·算法
2401_858286117 小时前
125.【C语言】数据结构之归并排序递归解法
c语言·开发语言·数据结构·算法·排序算法·归并排序
双叶8368 小时前
(C++)学生管理系统(正式版)(map数组的应用)(string应用)(引用)(文件储存的应用)(C++教学)(C++项目)
c语言·开发语言·数据结构·c++