• 二叉树的基本实现


    摘要

    一、定义和数据结构

    1. 定义

      二叉树(Binary Tree)是一种树形结构,它的特点是每个结点至多有两棵子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能随意颠倒。

    2. 数据结构

    typedef struct BiTNode
    {
        ElemType data;
        struct BiTNode *lchild, *rchild;
    } BiTNode, *BiTree;
    

      该结点是二叉树中最基本的元素,包括数据域和指针域。

    二、初始化和赋值

    1. 初始化

    BiTree myBiTree; // 定义一个指向二叉树根结点的指针
    
    InitTree(&myBiTree); // 初始化二叉树
    

      我们使用一个指向二叉树根结点的指针表示一颗二叉树。
      需要注意的是,二叉树的初始化InitTree改变的是根结点指针本身的内容,而不是指针指向的内容,所以在传递参数时,使用指针传递,传递根结点指针的指针,即根结点指针的地址。

    Status InitTree(BiTree *T)
    {
        // *T 即为指向二叉树根结点的指针.
        if (*T == NULL) // 若已经指向空, 操作失败, 报错.
        {
            return ERROR;
        }
    
        *T = NULL; // 使得指针指向 NULL.
    
        return OK;
    } // InitTree
    

    2. 赋值

      按照先序次序为二叉树结点赋值。

    // ! *T是二叉树指针的指针, **T才是二叉树本体.
    void CreateTree(BiTree *T, FILE *fp)
    {
        char ch = 0;
    
        ch = fgetc(fp); // 从输入文件中读取一个字符.
    
        if (ch == '^') // 使用'^'表示空结点.
        {
            *T = NULL;
        }
        else
        {
            // 为根结点指针分配要指向要内存空间.
            *T = (BiTNode *)malloc(sizeof(BiTNode));
            if (!*T)
            {
                exit(OVERFLOW);
            }
    
            (*T)->data = ch;
            CreateTree(&((*T)->lchild), fp); // 递归创建左右子树.
            CreateTree(&((*T)->rchild), fp); // 依旧传递指针的指针.
        }
    } // CreateTree
    

      在定义CreateTree时也可以不使用两层套娃, 但之所以仍像InitTree一样是因为:
        1. 保持一致性,凡是涉及到修改二叉树的操作,都传递指针的指针。
        2. 若以后修改二叉树的操作涉及对二叉树指针本身的修改,这么做可以减少麻烦。实际上CreateTree中的*T = NULL理解起来比&T = NULL方便.

    三、遍历方式

      遍历不修改二叉树,直接传递指针。

    1. 前序

    Status PreOrderTraverse(BiTree T, Status (*Visit)(ElemType e))
    {
        if (T)
        {
            if (Visit(T->data))
            {
                if (PreOrderTraverse(T->lchild, Visit))
                {
                    if (PreOrderTraverse(T->rchild, Visit))
                    {
                        return OK;
                    }
                }
            }
            return ERROR;
        }
        else
        {
            return OK;
        }
    } // PreOrderTraverse
    

    2. 中序

    Status InOrderTraverse(BiTree T, Status (*Visit)(ElemType e))
    {
        if (T)
        {
            if (InOrderTraverse(T->lchild, Visit))
            {
                if (Visit(T->data))
                {
                    if (InOrderTraverse(T->rchild, Visit))
                    {
                        return OK;
                    }
                }
            }
            return ERROR;
        }
        else
        {
            return OK;
        }
    } // InOrderTraverse
    

    3. 后序

    Status PostOrderTraverse(BiTree T, Status (*Visit)(ElemType e))
    {
        if (T)
        {
            if (PostOrderTraverse(T->lchild, Visit))
            {
                if (PostOrderTraverse(T->rchild, Visit))
                {
                    if (Visit(T->data))
                    {
                        return OK;
                    }
                }
            }
            return ERROR;
        }
        else
        {
            return OK;
        }
    } // PostOrderTraverse
    

    参考文献

    1. 数据结构:C语言版/严蔚敏,吴伟民编著. ——北京:清华大学出版社,2007

    代码仓库

    1. https://github.com/tianshihao/data-structure/tree/master/chapter_6
  • 相关阅读:
    nignx简单操作
    nginx的原理
    nginx简单了解
    操作数栈
    静态变量与局部变量
    遇到C语言内存错误怎么办?一定要找准这六个原因
    千万不要以为程序员是靠技术生存!六句话改变你对程序员的认知
    关于C语言Switch语句,先学这些技巧够不够?
    作为一个码农的悲哀:我是架构师,而你不是
    引用不如指针强大?C++引用,为你深度解析
  • 原文地址:https://www.cnblogs.com/tianshihao/p/12596063.html
Copyright © 2020-2023  润新知