当前位置:   article > 正文

【数据结构笔记】数据结构基础—树_左子树

左子树

1.树的原理

树(Tree)是n(n≥0)个节点的有限集合T,它满足两个条件 :

        1.有且仅有一个特定的称为根(Root)的节点;

        2.其余的节点可以分为m(m≥0)个互不相交的有限集合T1、T2、……、Tm,其中每一个集合又是一棵树,并称为其根的子树

表示方法 :树形表示法目录表示法

        一个节点的子树的个数称为该节点的度数

        一棵树的度数是指该树中节点的最大度数,

        度数为零的节点称为树叶终端节点,

        度数不为零的节点称为分支节点

        除根节点外的分支节点称为内部节点

  • 若树中每个节点的各个子树的排列为从左到右,不能交换,即兄弟之间是有序的,则该树称为有序树
  • m(m≥0)棵互不相交的树的集合称为森林
  • 树去掉根节点就成为森林,森林加上一个新的根节点就成为树。

2.二叉树

定义

        二叉树是n(n ≥ 0)个节点的有限集合;要么是空集(n=0),要么是由一个根节点以及两棵互不相交的、分别称为左子树和右子树的二叉树组成,严格区分左孩子和右孩子,即使只有一个子节点也要区分左右。

性质

性质1 二叉树第i层上的结点数目最多为2^(i-1),(i≥1)。
性质2 深度为k的二叉树至多有2^k-1个结点(k≥1)。
性质3 在任意-棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则no=n2+1。

顺序存储 

链式存储

  1. typedef int data_t;
  2. typedef struct node_t;
  3. {
  4. data_t data;
  5. struct node_t *lchild ,*rchild ;
  6. } bitree_t;
  7. bitree_t *root;
  8. 二叉树由根节点指针决定。

3. 二叉树的遍历

        遍历 :沿某条搜索路径周游二叉树,对树中的每一个节点访问一次且仅访问一次。

        二叉树是非线性结构,每个结点有两个后继,则存在如何遍历即按什么样的搜索路径进行遍历的问题。

由于二叉树的递归性质,遍历算法也是递归的。三种基本的遍历算法如下 :

        1.先访问树根,再访问左子树,最后访问右子树;(根左右)

        2.先访问左子树,再访问树根,最后访问右子树;(左根右)

        3.先访问左子树,再访问右子树,最后访问树根;(左右根)

 注:当遍历算法为左根右时,先对根节点A进行左根右判断,得到B,此时B有子树,那么把B当作根,继续左根右判断,发现没有左节点,根是B,故B入队,右是C,C有子树,那么把C当作根,继续左根右,D是左且没有子树,故D入队,根C入队,此时A的左侧遍历完成,根A入队,右为E,有子树,将E作为根,左没值,故E入队,右F有子树,来到左G,G有子树,来到左H,H没子树,H入队,根G入队,右K入队F入队,中序序列:BDCAEHGKF

 4.二叉树遍历的实现

创建树

  1. // 递归的方法
  2. bitree * tree_create() {
  3. data_t ch;
  4. bitree *r; // 根节点
  5. scanf("%c", &ch);
  6. if (ch == '#') // 符号# 用来表示这里的节点是空
  7. return NULL;
  8. if ((r = (bitree *)malloc(sizeof(bitree))) == NULL) {
  9. printf("malloc failed\n");
  10. return NULL;
  11. }
  12. r->data = ch;
  13. r->left = tree_create(); // 这里用 只有树根的树结构去理解
  14. r->right = tree_create(); // r->left和r->right均为NULL
  15. return r;
  16. }

这里使用了先序的方式来创建树,以上图为例,输入scanf 的序列应该是:

A B # C D # # # E # F G H # # K # # #

先序遍历

  1. void preorder(bitree * r) { // 先序遍历
  2. if (r == NULL) {
  3. return;
  4. }
  5. // 这三行的递归 也体现出了对于树的每个内部节点,都会将其视为根,进行根左右的遍历
  6. printf("%c", r->data);
  7. preorder(r->left);
  8. preorder(r->right);
  9. }

中序遍历

  1. void inorder(bitree * r) { // 中序遍历
  2. if (r == NULL) {
  3. return;
  4. }
  5. inorder(r->left);
  6. printf("%c", r->data);
  7. inorder(r->right);
  8. }

后序遍历

  1. void postorder(bitree * r) { // 后序遍历
  2. if (r == NULL) {
  3. return;
  4. }
  5. postorder(r->left);
  6. postorder(r->right);
  7. printf("%c", r->data);
  8. }

层次遍历

  1. // 代码整体看下来,就是按照树的层数由一层到末层、从左到右依次遍历
  2. void layerorder(bitree * r) { // 传入参数是树的根节点,不是整个树
  3. linkqueue * lq; // 用于访问
  4. if ((lq = queue_create()) == NULL)
  5. return;
  6. if (r == NULL)
  7. return;
  8. printf("%c", r->data);
  9. enqueue(lq, r); // 树根入队
  10. while (!queue_empty(lq)) {
  11. r = dequeue(lq); //循环①树根出队 循环②:左孩子出队 循环③:右孩子出队 循环④:左孩子的左右孙子继续循环
  12. if (r->left) {
  13. printf("%c", r->left->data); // 这就相当于遍历到了
  14. enqueue(lq, r->left);
  15. }
  16. if (r->right) {
  17. printf("%c", r->right->data);
  18. enqueue(lq, r->right);
  19. }
  20. }
  21. puts("");
  22. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/551334
推荐阅读
相关标签
  

闽ICP备14008679号