【数据结构】树-二叉树的遍历

  • 先序遍历
    先序遍历过程:
    1.访问根节点(输出其值)
    2.持续先序遍历其左子树,直到没有左子树后,退回上一节点
    3.先序遍历其右子树一次,再回到2
    不难看出这是类似走迷宫并且还有退回的一个方法,所以不难想到用递归来做。
    递归实现:
    在这里插入图片描述
    每走到一个新的点就将其输出,否则退回上一层的函数中
    图例:
    在这里插入图片描述
    从A开始,先输出A,再往左走,输出B,继续走输出D。
    D之后的D->Left == NULL,所以跳过if判断,此次调用结束,接下来到了D的->right,此时也是NULL,再次返回到D结点,由于两条路都走不通,所以回到B层,B层的->left已经结束,所以到下一条Right上,即走到了F。
    输出F,继续按照顺序先left,输出E,后来E与D的情况一致,回到F,F由于F->right==NULL,因此继续退回到B,由于B的左右两边都已经调用过了,所以退回到A,在A开始进行A->right的步骤,右边不多赘述。
    因此到最后输出的顺序应该为

A (B D F E) (C G H I)

  • 中序遍历
    遍历过程为:
    1.持续中序遍历其左子树,当左子树为空时进入2
    2.访问根节点(输出其值)
    3.中序遍历其右子树一次,再回到1
    代码和先序遍历几乎一样,主要就是访问根节点的顺序发生了变化
    在这里插入图片描述
    图例:
    在这里插入图片描述
    从A开始,一直往左走,直到D往左走不动后,输出D
    D再往右走,往右走也走不动了,返回到B,输出B
    B再往右走,遇到了F
    F开始往左走,走到E
    E往左走走不动,输出E
    往右走走不动,返回到F
    输出F,接下来F准备往右走,发现走不动,返回到B
    B两边都已经走过了,返回到A并输出A,右边不多赘述
    主旨:先往左走,走不动了输出,再往右走
    最后的输出顺序为:

(DBEF) A (GHCI)

  • 后序遍历
    遍历过程为:
    1.持续后序遍历其左子树,走不动了到2
    2.持续遍历其右子树,走不动了到3
    3.访问根节点(输出其值)
    言简意赅:完全走不动了就输出这个值并返回上一个结点
    在这里插入图片描述
    在这里插入图片描述
    先A一直往左走直到D
    D往右走走不动,输出D,并返回到B
    B往左走走不动,往右走到F,F往左走到E,E左右都走不动,输出E,并返回到F
    F往右走走不动,输出F,返回B
    B左右两边都走过了,输出B,返回A
    A往右走到C,C开始往左走到G,G往左走走不动,往右走到H,H两边都走不动,输出H,返回G
    G两边都走完了,输出G,返回C
    C往右走到I,I两边走不动,输出I,返回C
    C两边都走过了,输出C,返回A,A两边都走过了,递归结束。
    因此输出结果为:

(D E F B)(H G I C) A

小总结:先序、中序、后续的遍历路径都是相同的,唯一不同的是访问各节点的时间,导致最后的结果也会有不同
先序——第一次碰到它就输出,最先访问树根
中序——第二次碰到它就输出,在中间位置访问到树根
后续——第三次碰到它就输出,最后访问到树根
在这里插入图片描述

  • 中序遍历,先序遍历的非递归算法实现:
    基本思路:使用堆栈
    每走到一个节点,将这个节点入栈,然后到左边走不动了,抛出并访问它
    在这里插入图片描述
    起点开始,A放入堆栈,往B走
    B放入堆栈,往D走
    D放入堆栈,往左走不动,将D抛出,往右走不动,返回到B(此时要访问的节点就是堆栈栈头,即B)
    B已经走过左边了(第二次遇到),将B抛出,往右走
    F放入堆栈,再往左边走,放入E
    E走不动,抛出,回到F,将F抛出,F往右走,走不动,返回到A(此时B已经被抛出了,堆栈中只剩下A)
    A抛出,往右走,将C放入,后面不多赘述
    在这里插入图片描述
    这里对A抛出后的情况解释一下:
    在这里插入图片描述
    T指向A节点,然后T=T->Right,向右走
    此时T=C节点,在while(T || !IsEmpty(S))中,||表示的是或运算,只要有一个满足true就能继续下去,此时S是空,返回false,但是T!=NULL,因此可以继续。
    直到最后I被抛出后,I->Right为空(false),堆栈也为空(!true == false),外循环才结束。
    先序遍历的非递归代码几乎相同,只不过访问(输出)的顺序问题,在第一次遇见的时候就输出,所以把printf直接放到Push()的上面就好了。

  • 层次遍历
    队列实现:遍历从根节点开始,首先将根节点入队,然后执行循环:
    节点出队、访问该节点、将其左右儿子入队(没有就算),直到队列为空
    口嗨:
    在这里插入图片描述
    A先放到队列里,然后将队头(A)的左右两边(B,C)入队,输出队头并抛出
    将队头(B)的左右两边(D,F)入队,输出队头并抛出
    将队头(C)的左右两边(G,I)入队,输出队头并抛出
    将队头(D)的左右两边(没东西就不入队),输出队头并抛出
    直到最后,将H输出并抛出,此时队列元素为空,循环结束
    输出顺序为:

A (B C) (D F G I) (E H)
不难看出,输出是一层一层输出的

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值