二叉树(Binary Tree)的创建与遍历——C语言实现

本文的写做目的在于巩固本身在数据结构和C语言方面的基础知识,提高写代码的基本功。本文的代码参考了浙大MOOC数据结构中的演示代码以及《大话数据结构》中的演示代码,由于运行没有结果显示加上发现本身对C语言指针的理解不到位,因而又参考了另外两个博主的代码。很是感谢浙大的何钦铭老师以及两位博主。
其一参考简书博主EarthChen
其二参考csdn博主men_wen数据结构

1、运行环境简介

🦄编辑器:VSCode + MicroSoft原生插件;
🐱‍🐉运行环境: MinGW ;
🐱‍👤经常使用指令: gcc mian.c -o mian.exe编辑器

2、二叉树的定义

这里咱们直接采用浙大数据结构课程中的代码。由于这种写法清晰明了,且便于后续扩展。函数

typedef char ElementType;

typedef struct TNode *Position; /* 结构体指针 */
typedef Position BinTree; /* 二叉树类型 */
struct TNode{ /* 树结点定义 */
    ElementType Data; /* 结点数据 */
    BinTree Left;     /* 指向左子树 */
    BinTree Right;    /* 指向右子树 */
}TNode;
复制代码

3、如何建立一个二叉树?

先看代码再分析测试

void CreateBinaryTree ( BinTree *T ) {
    ElementType ch;
    scanf("%c",&ch);

    if (ch == '#')
        *T = NULL;
    else {
        *T = (BinTree)malloc(sizeof(TNode));
        (*T)->Data = ch;
        CreateBinaryTree(&((*T)->Left));
        CreateBinaryTree(&((*T)->Right));
    }
}
复制代码

1.解决此函数的形参疑问
咱们知道,二叉树的类型被咱们定义为BinTree,而它的原类型是指向二叉树结点TNode的指针。我一开始犯的错误是,我认为直接传入这里的指针BinTree给函数CreateBinaryTree()就能够获得建立的二叉树。事实上这里须要传入指针的指针,即这个结构体指针的地址*BinTree。 也就是说,咱们事实上传入的是** TNode,即结点指针的指针。而采用上面的定义,就至关因而一个降维的过程,咱们能够少写一个*。
为何要传入结点指针的指针呢?个人理解是,咱们所使用的数据结构二叉树在基本操做中就依赖于指针,这至关于咱们一开始就在操控指针(好比不修改二叉树的一些操做——先序中序后序遍历中,咱们用到了指针),但这些指针是包含在二叉树这个类型中的,打个比方,就至关于一个没有取得其地址的普通类型。因此咱们须要修改二叉树的时候,咱们要考虑取所谓“普通类型”的地址,即咱们要取指针的地址,所以咱们会在CreateBinaryTree()中传入结点指针的指针,即** TNode,又即*Bintree
2.对代码的一些说明
这里创建的二叉树,其实是扩展二叉树,这里采用先序遍历的顺序依次输入结点的值(char类型),用'#'表明空结点。
例如:建立二叉树:第一层为A,第二层为B、C,第三层为D、F,D为B的左孩子,F为C的右孩子;咱们须要输入ABD###C#F##大数据

4、二叉树的遍历——递归实现

3种递归实现仅仅是输出语句顺序不一样。
其实现原理为
二叉树的先中后序遍历中通过的结点路径是同样的,可是访问各结点的时机不一样,每一个结点都会被通过三次,第一次通过就printf是先序,同理第二次printf是中序,第三次是后序。
1.先序遍历ui

void PreOrderTraversal ( BinTree BT ) {
    if ( BT ) {
        printf("%c", BT->Data);
        PreOrderTraversal( BT->Left );
        PreOrderTraversal( BT->Right );
    }
}
复制代码

2.中序遍历spa

void InOrderTraversal ( BinTree BT ) {
    if ( BT ) {
        PreOrderTraversal( BT->Left );
        printf("%c", BT->Data);
        PreOrderTraversal( BT->Right );
    }
}
复制代码

3.后序遍历.net

void PostOrderTraversal ( BinTree BT ) {
    if ( BT ) {
        PostOrderTraversal( BT->Left );
        PostOrderTraversal( BT->Right );
        printf("%c", BT->Data);
    }
}
复制代码

5、其余操做

1.先序遍历输出二叉树叶子结点插件

void PreOrderPrintLeaves ( BinTree BT ) {
    if ( BT ) {
        if ( !BT->Left && !BT->Right )
            printf("%c", BT->Data);
    PreOrderPrintLeaves( BT->Left );
    PreOrderPrintLeaves( BT->Right );
    }
}
复制代码

2.后序遍历求二叉树的高度3d

int PostOrderGetHeight ( BinTree BT) {
    int HL, HR, MaxH;

    if ( BT ) {
        HL = PostOrderGetHeight( BT->Left );
        HR = PostOrderGetHeight( BT->Right );
        MaxH = ( HL > HR ) ? HL : HR;
        return (MaxH + 1);
    }
    else
        return 0;
}
复制代码

6、测试

程序结构:
头文件为BTree.h,里面包含上述代码。主要程序文件为main.c,包含代码以下:

#include<stdio.h>
#include<stdlib.h>
#include"BTree.h"

int main() {
  BinTree myTree;
  printf("Create your Binary Tree:\n");
  CreateBinaryTree(&myTree);
  printf("\n PreOrder:");
  PreOrderTraversal(myTree);
  printf("\n InOrder:");
  InOrderTraversal(myTree);
  printf("\n PostOrder:");
  PostOrderTraversal(myTree);
  printf("\n Leaves:");
  PreOrderPrintLeaves(myTree);
  printf("\n");
  int high = PostOrderGetHeight(myTree);
  printf("The height of the tree: %4d", high);
  return 0;
}
复制代码

测试结果以下:

测试

7、结语

本文解决了我关于二叉树建立的疑惑,以前写链表的时候应该也是这个问题,只是当时没有深刻思考,趋之若鹜地使用了cpp的引用,今天稍微思考了一下,也可能有错误的地方,但由于还须要复习别的内容,因此暂时先写到这里。写递归实现遍历和结尾的测试程序只是为了方便读者快速运行代码。后续可能会更新非递归实现二叉树的遍历。感谢阅读!

相关文章
相关标签/搜索