二叉树基本操作:前序、中序、后序遍历(递归方式)

  二叉树是最常见最重要的数据结构之一,它的定义如下:

  二叉树(binary tree)是有限多个节点的集合,这个结合或者是空集,或者由一个根节点和两颗互不相交的、分别称为左子树和右子树的二叉树组成。

  二叉树最基本的操作是遍历:一般约定遍历时左节点优先于右节点,这样根据根节点的遍历顺序可分为三种遍历操作:前序-先遍历根节点,再处理左右节点;中序-先遍历左节点,然后处理根节点,最后处理右节点;后序-先遍历左右节点,然后处理根节点。

  从上边二叉树定义可以看出:二叉树使用了递归的概念描述。所以,二叉树的很多操作都可以很方便的通过递归来实现,当中当然包裹遍历操作。实际上,三种遍历操作的递归实现,是二叉树其他大多数操作实现的基础:绝大多数其他操作都可以在三种遍历中的一种的基础上变化而来。

  二叉树通常有两种存储方式:顺序存储和链式存储。本文代码基于链式存储方式实现,链式存储节点定义如下:

typedef struct node *tree_pointer;
typedef struct node {
    //为了简化,节点数据用整型
    int data;
    //指向当前节点左儿子和右儿子的指针
    tree_pointer left_child, right_child;
};

给出的节点定义中只有指向当前节点的左儿子和右儿子的指针,如果需要方便的知道当前的节点的父节点,可以在定义中增加指向父节点的指针: tree_pointer parent;

  有了节点的定义,就可以编写二叉树的遍历函数,我们先给出递归中序遍历函数:

1 void inorder(tree_pointer ptr)
2 {
3     if (ptr) {
4         inorder(ptr->left_child);
5         printf("\t%d", ptr->data);
6         inorder(ptr->right_child);
7     }
8 }

函数本身非常简洁,下面我们以图示的二叉树解释函数的遍历过程:

如上图所示,这颗二叉树有九个节点:ABCDEFGHI,红线连接的“节点”表示叶子节点的“左右儿子”(实际上叶子节点没有左右儿子,这里便于描述,假设存在这些NULL节点)

根据中序遍历的定义,我们可以得到这颗二叉树的中序遍历结果为:HFIDGBEAC.

把这颗二叉树的root节点指针作为参数传递给inorder函数,则函数的执行过程如下:

调用函数: inorder(root);

(下面步骤号为调用inorder函数的顺序次数)

1. 第一次调用inorder,ptr指向A,函数进入if结构,执行第四行代码,第二次调用inorder,参数为A的左儿子B;

2. ptr->B,进入if,执行line4,第三次调用inorder: inorder(B->left_child);

3. ptr->D,进入if,line4,第四次调用:inorder(D->l_c);

4. ptr->F, if, line4: inorder(F->l_c);

5. ptr->H, if, line4: inorder(H->lc);

6. ptr->NULL, 没有进入if, return;

5. 执行line5,printf(H),执行line6: inorder(H->rc);

7. ptr->NULL, 没有进入if, return回 5 ,5已经执行完毕,return 回4;

4. line5,printf(F),line6: inorder(F->rc);

8. ptr->I, if, line4: inorder(I->lc);

9. ptr->NULL, return-8;

8. line5, printf(I), line6: inorder(I->rc);

10. ptr->NULL, return-8, 8 完成,return-4, 4完成, return-3;

3. line5:printf(D), line6: inorder(D->rc);

11. ptr->G, line4: inorder(G->lc);

12. ptr->NULL, return-11;

11. line5: printf(G), line6: inorder(G->rc);

13. ptr->NULL, return-11, 11完, return-3, 3完,return-2;

2. line5:printf(B), line6:inorder(B->rc);

14. ptr->E, line4: inorder(E->lc);

15. ptr->NULL, return-14;

14. line5: printf(E), line6: inorder(E->rc);

16. ptr->NULL, return-14, 14 finished, return-2, 2 finished, return 1;

1. line5: printf(A), line6: inorder(A->rc);

17. ptr->C, line4: inorder(C->lc) ;

18. ptr->NULL, return-17;

17. line5: printf(C); line6: inorder(C->rc);

19. ptr->NULL, return-17, 17 finished, return 1, 1 finished ,return 回调用函数

完成。

  上面的步骤手动描述了递归中序遍历的执行过程,其中暗含了递归调用的入栈出栈过程。

  前序和后序的递归遍历与中序类似,代码实现如下:

//前序遍历
void preorder(tree_pointer ptr)
{
    if (ptr) {
        printf("\t%d", ptr->data);
        preorder(ptr->left_child);
        preorder(ptr->right_child);
    }
}

//后序遍历
void postorder(tree_pointer ptr)
{
    if (ptr) {
        postorder(ptr->left_child);
        postorder(ptr->right_child);
        printf("\t%d", ptr->data);
    }
}

函数的执行过程也与中序基本一样,不再描述。

  (在下一篇文章中将给出这些遍历函数的完整测试代码)

二叉树基本操作:前序、中序、后序遍历(递归方式),布布扣,bubuko.com

时间: 2024-10-08 06:55:49

二叉树基本操作:前序、中序、后序遍历(递归方式)的相关文章

分别求二叉树前、中、后序的第k个节点

一.求二叉树的前序遍历中的第k个节点 //求先序遍历中的第k个节点的值 int n=1; elemType preNode(BTNode *root,int k){ if(root==NULL) return ' '; if(n==k) return root->data; n++; elemType ch = preNode(root->lchild,k); if(ch!=' ') return ch; ch = preNode(root->rchild,k); return ch;

算法实验-二叉树的创建和前序-中序-后序-层次 遍历

对于二叉树的创建我是利用先序遍历的序列进行创建 能够对于树节点的内容我定义为char型变量 '0'为空,即此处的节点不存在 头文件 Tree.h //链式二叉树的头文件 #pragma once #include<iostream> #include<queue> using namespace std; class BinaryTreeNode { public: char data; BinaryTreeNode *leftChild,*rightChild; BinaryTr

二叉树的前序中序后序遍历相互求法

二叉树的前中后序遍历,他们的递归非递归.还有广度遍历,参见二叉树的前中后序遍历迭代&广度遍历和二叉树的前中后序遍历简单的递归 现在记录已知二叉树的前序中序后序遍历的两个,求另外一个.一般,这两个中一定有中序遍历. 1.已知前序和中序,求后序遍历: 前序:ABDECFG  中序:DBEAFCG 思路简单:前序的第一个节点就是根节点, 中序中找到根节点的位置,根节点之前是其左子树,之后是右子树   按此顺序,依次在左子树部分遍历,右子树部分遍历 C++ 代码: TreeNode *BinaryTre

已知二叉树前、中序遍历,求后序 / 已知二叉树中、后序遍历,求前序

void solve(int start,int end,int root) { // 前序和中序 -> 后序 // 每次调用solve()函数,传入pre-order的start,end,root if (start > end) // 递归边界 return; int i = start; while (i < end && in.at(i) != pre.at(root)) // 找到左右子树的分割点 i++; solve(start, i - 1, root +

经典白话算法之二叉树中序前序序列(或后序)求解树

这种题一般有二种形式,共同点是都已知中序序列.如果没有中序序列,是无法唯一确定一棵树的. <1>已知二叉树的前序序列和中序序列,求解树. 1.确定树的根节点.树根是当前树中所有元素在前序遍历中最先出现的元素. 2.求解树的子树.找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树.若根节点左边或右边为空,则该方向子树为空:若根节点 边和右边都为空,则根节点已经为叶子节点. 3.递归求解树.将左子树和右子树分别看成一棵二叉树,重复1.2.3步,直到所有的节点完成定

日常学习随笔-用链表的形式实现普通二叉树的新增、查找、遍历(前、中、后序)等基础功能(侧重源码+说明)

一.二叉树 1.二叉树的概念 二叉树是每个节点最多有两个子树的树结构.通常子树被称作"左子树"(left subtree)和"右子树"(right subtree),其次序不能任意颠倒. 2.性质 (1)若二叉树的层次从0开始,则在二叉树的第i层至多有2^i个结点(i>=0): (2)高度为k的二叉树最多有2^(k+1) - 1个结点(k>=-1). (空树的高度为-1): (3)对任何一棵二叉树,如果其叶子结点(度为0)数为m, 度为2的结点数为n,

算法进阶面试题03——构造数组的MaxTree、最大子矩阵的大小、2017京东环形烽火台问题、介绍Morris遍历并实现前序/中序/后序

接着第二课的内容和带点第三课的内容. (回顾)准备一个栈,从大到小排列,具体参考上一课.... 构造数组的MaxTree [题目] 定义二叉树如下: public class Node{ public int value; public Node left; public Node right; public Node(int data){ this.value=data; } } 一个数组的MaxTree定义如下: ◆ 数组必须没有重复元素 ◆ MaxTree是一颗二叉树,数组的每一个值对应一

二叉树的遍历方法之层序-先序-中序-后序遍历的简单讲解和代码示例

二叉树的基础性质及二叉树的建立参见前面两篇博文: http://blog.csdn.net/why850901938/article/details/51052936 http://blog.csdn.net/why850901938/article/details/51052156 首先为了讲解方便,我建立了如图所示的二叉树: 取名为:树A 1.何为层序遍历? 层序遍历就是按照二叉树的层次由上到下的进行遍历,每一层要求访问的顺序为从左到右: 以树A为例,层序遍历得到的结果为: 5 2 6 1

二叉树的先序-中序-后序遍历(一)-循环----绝对白痴好记的方法

接着上一篇 二叉树的先序-中序-后序遍历(一)-递归 的讲,这篇该循环遍历了. 之前一直没有找到好的方法来循环遍历树,以前我老认为有些递归的能做的东西很难换成循环实现. 后来看了一些别人写的代码,然后又问了朋友,才发现...哦,原来这样的啊,我可以自己弄个栈来维护一下. 想到了可以弄个栈以后,至少在我认为,把递归转成循环已经是可行的了,至于怎么实现,这几天在想(因为太笨,看人家的代码总看一半就不想看),今天找到了一个好用的方法,在这里分享一下. 算法的核心是:你看二叉树的时候心里怎么想的,程序就

前序中序后序遍历非递归实现

#include<iostream> #include<vector> #include<stack> #include<string> #include<algorithm> #include<numeric> using namespace std; class node{ public: int val; node* left; node* right; node():val(0),left(NULL),right(NULL){