数据结构---二叉树(C语言看了就懂教程)

1.概念

    二叉树就是一个结点最多只有两个分叉的树

2.性质

    ①在二叉树的第n层最多只有2^(n-1)个结点(i >= 1);

    ②深度为k的二叉树至多有2^k - 1个结点(k >= 1);

    ③对任何一颗二叉树T,如果其终端节点数为N0,度(几个子结点)为2的结点数为N2,则N0 = N2+1;

3.二叉树的形态

    ①满二叉树---(除了最下面一层所有的结点度都为2)

    ②完全二叉树---(叶子结点只可能在层次最大的两层出现,且最后一层叶子结点出现顺序都为从左到右)

    ③非完全二叉树---(不符合上面两种要求就是非完全)

4.二叉树的两种存储方式

        ①顺序存储结构

    利用率高,寻找双亲和孩子比较简单,但是在插入删除操作比较难,一般只适用于完全二叉树

    typedef TElemType SqBiTree[100];    //0号单元存储根结点

    SqBiTree bt;

    ②链式存储结构

    常用的存储结构,结构体含有数据元素,左孩子指针,右孩子指针,寻找孩子节点简单,双亲节点难,若需要频繁寻找双亲,则添加一个指向双亲结点的指针域   

 typedef struct Bitree

    {

        char data[30];                  //存储数据

        struct Bitree *lchild;          //左孩子

        struct Bitree *rchild;          //右孩子

    }BiTree , *BiTree_list;

5.遍历二叉树

    ①三种方法:

        先序序列,中序序列,后序序列

        先序:先访问根->访问左->访问右

        中序:先访问左->访问根->访问右

        后序:先访问左->访问右->访问根

    ②代码实现逻辑:

        先序:先访问根的话就不管什么先打印根结点的数据域信息,再判断是否有左结点,打印左结点,然后再判断是否有左结点,有就打印,没有就判断根结点是否有右结点,若也没有就判断上一级根节点是否有右孩子

        中序:先判断是否有左孩子树,递归判断,然后找到最左边的结点,再返回打印根结点,再判断右结点,右结点同样判断出最左边的结点,然后打印根结点。其顺序就是先左后根再右。

        后序:先找出的根结点最左边的结点打印数据域,然后判断改根结点是否有右结点,然后再重复判断该右结点有没有左结点,重复操作直到,没有左孩子树,再打印右结点,最后打印根结点。

        以上操作是递归判断的方法,每个结点都可以当作根结点,然后进行判断。


        实例函数(中序遍历)---理解的时候可作图进行分析:       

//中序递归遍历二叉树

        void InOrderTraverse(BiTree *T)

        {

            if(T)

            {

                InOrderTraverse(T->lchild);   //先遍历左

                printf("data :%c\n",T->data); //打印根

                InOrderTraverse(T->rchild);   //再遍历右

            }

        }

        中序非递归遍历二叉树---非递归遍历二叉树的逻辑其实跟递归差不多,都是先判断的后执行,所以此时就可以考虑使用栈啊,数组,队列啊,这种由顺序的存储结构

        本文的例子写的是栈的方式,顺便理解栈的概念,实现逻辑和本质。       

void InOrderTraverse2(BiTree *T)

        {

            SqStack  S;                                 //先创建一个栈指针

            InitStack(S);                               //初始化栈

            BiTree *p = T;                              //定义p指针指向根结点

            BiTree *q;

            q = (BiTree*)malloc(sizeof(BiTree));        //定义结点空间q,存放出栈数据                          

            while (p || EmptyStack(S))                  //树不为空,栈不为空

            {  

                /* code */

                if(p)                                   //该结点不为空,则进行下一步

                {

                    Push(S,p);                          //将该结点入栈

                    p=p->lchild;                        //找到最左边结点

                }

                else

                {

                    Pop(S,q);                           //为空则说明找到最左边节点,将其出栈,并存入事先准备好,存储空间中

                    puts(q->data);                      //使用puts函数将字符串打印输出

                    p=q->rchild;                        //当rchild结点判断为空的话,打印的就是上一个结点的根结点

                }

            }

        }

    以上就是有关中序遍历二叉树的一个逻辑,其实只需根据图例找出规律就可以推导出先序,后序遍历(这些留给大家去思考)

6.二叉树的顺序建立

        创建二叉树---(已知二叉树先序遍历的字符顺序,去创建二叉树)       

//先序创建二叉树

        BiTree *CreateBiTree()

        {

            printf("please input Node element ,and '#'== 'NULL':");

            getchar();

            char ch;

            BiTree *T;

            scanf("%c",&ch);                            //输入二叉树结点的元素

            if(ch == '#')

            return  NULL;

            T = CreateNode(ch);                     //创建新的结点空间

            T->lchild = CreateBiTree();             //循环递归左孩子结点  ---左

            T->rchild = CreateBiTree();             //循环递归右孩子结点  ---右

            return T;

        }

        例如输入字符为 'ABCD###E##FG###'

        那么其先序建立的二叉树应该是下图所示:

上述内容就是对于数据结构这一门课程中二叉树基本操作的思路讲解,大家可以参照这些内容配合自己学习进行理解。

想要源码的随时私信,或者评论区说一声,一起交流!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

底层电工人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值