树与二叉树(定义和遍历算法)

540 阅读2分钟

这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

1.定义

  • 树:是n个有限数据元素的集合(n>=0)

其树相关的术语:

结点:图中有6个结点

结点的度: 一个结点的孩子个数为结点的度 如B的度为2

叶子结点: 度为0的结点 也可以说没有孩子的结点 如图中D,E,F

分支结点: 度不为0的结点 如图中 A,B,C

兄弟结点: 具有相同父亲的结点 如D,E为兄弟结点

树的层数: 树的根结点为第一层 其余结点的层为双亲结点层数加1 其中树的层数3

树的深度: 树中结点的最大层数为数的深度

image.png 图a

2.二叉树

  • 二叉树:是每个结点最多有两颗子树(结点的度小于等于2)且二叉树有左右之分 不能任意颠倒次序
  • 满二叉树: 深度为k且有 2k-1 个结点的二叉树 其每一层上的结点数都是最大结点数
  • 完全二叉树: 对满二叉树的结点进行连续编号,约定编号从根结点起,自上而下,自左至右。深度为k的,有n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应,称之为完全二叉树

3.二叉树的性质:

1.在二叉树的第i层最多有2^(i-1)

2.深度为k的二叉树最多有2^k - 1 个结点

3.对任何一棵二叉树T,如果其度为0的结点个数为n0,度为2的结点数为n2,则 n0 = n2 + 1

4.具有n个结点的完全二叉树的深度为 ⌊log2n⌋+1

  1. 对一棵有n个结点的完全二叉树按层序编号则对任一结点i(1<=i<=n),有:

(1)如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲为⌊i/2⌋

(2)如果2i>n,则结点i无左孩子(结点i为叶子结点);2i<=n 则i结点的左孩子结点序号是2i

(3)如果2i+1>n,则结点i无右孩子;2i+1<=n否则其右孩是2i+1

4. 存储结构

  • 顺序存储结构 用一组连续的存储单元存放二叉树的结点 如图a 我们最后存放就是 image.png
#define MaxSize 100
typedef struct {
  char tree[MaxSize];
  int treeNum;
}BiTreec
  • 链式存储 用链表来表示一棵二叉树 根据二叉树的特点,我们可知一个结点应该包含三个部分 一个指向左孩子的指针 一个指向有孩子的指针和一个数据域 image.png
typedef struct node{
 char data;
 struct node *lchild,*rchild;
}BiTree;

4.二叉树的遍历(递归实现)

  • 前提
typedef struct Node{
  char Data;
  struct Node *left,*right;
}BiTNode;*BiTree

//创建二叉树 T是一个二级指针
void createBiTree(BiTree *T){
   int data;
   scanf("%c",&data);
   if(data=="*"){
     T=NULL;
   }else{
     *T=(BiTree)malloc(sizeof(BiTNode));
     (*T)->data = data;
     createBiTree((*T)->lchild);
      createBiTree((*T)->rchild);
   }
  
    }
  • 前序遍历
 void preOrder(BiTree T){
   if(T==NULL) retrun ;
   printf("%c",T->data);
   preOrder(T->lchild);
   preOrder(T->rchild)
 }
  • 中序遍历
 void midOrder(BiTree T){
   if(T==NULL) retrun ;
   midOrder(T->lchild);
   printf("%c",T->data);
   midOrder(T->rchild)
 }
  • 后序遍历
 void rearOrder(BiTree T){
   if(T==NULL) retrun ;
   rearOrder(T->lchild);
   rearOrder(T->rchild)
   printf("%c",T->data);
 }