二叉树

二叉树,每个结点⾄多只有2颗⼦树

二叉树示意图

结点的⾼度: 结点到叶⼦结点的最⻓路径(边数),  结点 -> 叶子结点

结点的深度: 根结点到这个结点所经历的边的个数, 结点 -> 根节点

结点的层数: 结点的深度-1

树的⾼度 : 根结点的⾼度

层序遍历:根结点开始访问,从上⽽下逐层遍历,在同⼀层中, 按从左到右的顺序对结点逐个访问

层序遍历

完全⼆叉树:结点 从上⽽下逐层,从左到右的顺序 都存在

完全⼆叉树&满二叉树

去掉3, 不是完全二叉树

去掉5, 不是满二叉树,是完全二叉树

完全二叉树,顺序结构储存具备下面特性, 结点从1开始编号

A.如果i>1,那么序号为i的结点的双亲结点序号为i/2; 

B.如果i=1,那么序号为i的结点为根节点,无双亲结点; 

C.如果2i<=n,那么序号为i的结点的左孩子结点序号为2i; 

D.如果2i>n,那么序号为i的结点无左孩子; 

E.如果2i+1<=n,那么序号为i的结点右孩子序号为2i+1; 

F.如果2i+1>n,那么序号为i的结点无右孩子。

G 有n个结点的完全二叉树深度为(log2(n))+1 

二叉树遍历

前序遍历:遍历顺序 根结点 -> 左⼦树 -> 右⼦树

前序遍历

中序遍历:遍历顺序 左⼦树 -> 根结点  -> 右⼦树

中序遍历

后序遍历:遍历顺序 左⼦树  -> 右⼦树 -> 根结点

后序遍历

遍历

遍历

二叉树创建代码实现

1.顺序结构

定义一个数组储存,长度是100

typedef CElemType SqBiTree[MAX_TREE_SIZE]; 

数据是根据 二叉树的层序遍历顺序得到的

Status CreateBiTree(SqBiTree T){

    int i =0;

    /*

     1      -->1

     2    3  -->2

     4  5  6  7 -->3

     8  9 10      -->4


     1 2 3 4 5 6 7 8 9 10 Nil Nil Nil

     */


    while(i <10) {

        T[i] = i+1;

        printf("%d ",T[i]);

        //结点不为空,且无双亲结点

        if(i !=0&& T[(i+1)/2-1] ==Nil&& T[i] !=Nil) {

            printf("出现无双亲的非根结点%d\n",T[i]);

            exit(ERROR);

        }

        i++;

    }

    //将空赋值给T的后面的结点

    while (i < MAX_TREE_SIZE) {

        T[i] =Nil;

        i++;

    }

    return OK;

}

获取二叉树的深度, 是一个完全二叉树,深度为(log2(n))+1 

int BiTreeDepth(SqBiTree T){

    int j = -1;

    int i;

    //找到最后一个结点

    //MAX_TREE_SIZE -> 100 -> 10 目的找到最后一个结点10的位置

    for(i =MAX_TREE_SIZE-1; i>=0; i--) {

        if(T[i] !=Nil)

            break;

    }

    do {

        j++;

    } while (powl(2, j) <= i);//计算2的次幂

    return j;

}

获取结点的双亲, 完全二叉树特性:i / 2

获取结点的左孩子:2i

获取结点的右孩子:2i + 1

获取结点的兄弟结点:i + 1  或 i - 1

前序遍历: 根结点 -> 左结点 -> 右结点

递归 完成

递归 入口

Status PreOrderTraverse(SqBiTree T){

    //树不为空

 if(!BiTreeEmpty(T)) {

        PreTraverse(T,0);

    }

    printf("\n");

 return OK;

}

void PreTraverse(SqBiTree T,int e){

    //打印结点数据  根结点

    visit(T[e]);

    //先序遍历左子树

    if(T[2* e +1] !=Nil) {

        左结点

        PreTraverse(T,2*e+1);

    }

    //最后先序遍历右子树

    if(T[2* e +2] !=Nil) {

      右结点

        PreTraverse(T,2*e+2);

    }

}

2. 链表结构

结点 结构体

typedef struct BiTNode  /* 结点结构 */

{

    CElemTypedata;        /* 结点数据 */

    structBiTNode*lchild,*rchild;/* 左右孩子指针 */

} BiTNode,*BiTree;

数据(前序遍历顺序) ABD##E#H#K##CFI###G#J##(# 空)

按前序输入二叉树中的结点值(字符),#表示空树

void CreateBiTree(BiTree *T){

    CElemType ch;

    //获取字符

    ch =str[indexs++];

    //判断当前字符是否为'#'

    if(ch =='#') {

        *T =NULL;

    }else {

        //创建新的结点

        *T = (BiTree)malloc(sizeof(BiTNode));

        //是否创建成功

        if(!*T) {

            exit(OVERFLOW);

        }

        /* 生成根结点 */

        (*T)->data= ch;

        /* 构造左子树 */

        CreateBiTree(&(*T)->lchild);

        /* 构造右子树 */

        CreateBiTree(&(*T)->rchild);

    }

}

二叉树T的深度 不懂(代码断点调试)

int BiTreeDepth(BiTree T){

    int i,j;

    if(!T)

        return 0;

    //计算左孩子的深度

    if(T->lchild)

        i=BiTreeDepth(T->lchild);

    else

        i=0;

    //计算右孩子的深度

    if(T->rchild)

        j=BiTreeDepth(T->rchild);

    else

        j=0;

    //比较i和j

    return i>j?i+1:j+1;

}

前序遍历 递归完成

void PreOrderTraverse(BiTree T)

{

    if(T==NULL)

        return;

    printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */

    PreOrderTraverse(T->lchild); /* 再先序遍历左子树 */

    PreOrderTraverse(T->rchild); /* 最后先序遍历右子树 */

}

线索二叉树, 结点的左结点或右结点为空的话,赋值 当前结点的前驱或后继

创建一个虚拟头结点

线索二叉树

中序遍历

Link==0表示指向左右孩子指针

Thread==1表示指向前驱或后继的线索

typedef enum {Link,Thread} PointerTag;

线索二叉树存储结点结构

typedef struct BiThrNode{

    //数据

    CElemType data;

    //左右孩子指针

    struct BiThrNode *lchild, *rchild;

    //左右标记

    PointerTag LTag;

    PointerTag RTag;

} BiThrNode, *BiThrTree;

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容