数据结构(5)-二叉树

一、概念

1.线性结构:描述数据一对一的关系(表)

2. 非线性结构:描述数据一对多(树)、多对多(图)的关系

二、树形结构

1. 节点:组成树形结构的一个小的单元称为节点

根节点:只有后继,没有前驱

分支节点:既有前驱,又有后继

叶子节点:只有前驱,没有后继

2. 前驱(祖先):由哪个节点可以访问到该节点

3. 后继(子孙):该节点可以后续访问到哪些节点

4. 层:根节点层数为1,后续每引申出的一个节点就在该节点层数上+1

5. 树的层树:树的层数由层数最高的节点对应的层数表示树的层数

6. 高度:节点高度是由该节点到最远的叶子节点的距离表示该节点高度

7. 深度:节点深度是由该节点到根节点的距离表示节点深度

8. 树的高度 == 树的深度 == 树的层数

9. 度:后继节点的个数

三、二叉树

1. 树形结构中的所有节点度数最大为2,称为二叉树

2.二叉树节点类型

3. 满二叉树和完全二叉树:

(1)满二叉树:

所有叶子节点均在同一层,且每层节点个数均为最大值

特性:满二叉树第k层节点有2^(k - 1)    满二叉树前k层节点有2^k-1

(2) 完全二叉树:

二叉树的编号(如果节点编号为n,左孩子编号:2n,右孩子编号为:2n+1)展开后是连续的,称为完全二叉树

(3)完全二叉树的遍历形式:

深度优先遍历(DFS)

前序遍历(先序遍历):根左右

中序遍历:左根右

后序遍历:左右根

广度优先遍历(BFS)

层序遍历:逐层从左到右依次遍历

4.完全二叉树的操作

(1)节点定义

typedef struct node{
    int no;
    struct node *pleftchild;
    struct node *prightchild;
}treenode;

(2)创建完全二叉树

通过函数递归完成完全二叉树的创建

申请节点空间

存放数据编号

如果存在左子树递归创建左子树

如果存在右子树递归创建右子树

treenode *creat_complete_btree(int startno, int endno)
{
    treenode *ptmpnode = NULL;

    ptmpnode = malloc(sizeof(treenode));
    if (NULL == ptmpnode)
    {
        perror("fail to malloc");
        return NULL;
    }

    ptmpnode->no = startno;
    if (2*startno <= endno)
    {
        ptmpnode->pleftchild = creat_complete_btree(2*startno, endno);
    }
    if(2*startno+1 <= endno)
    {
        ptmpnode->prightchild = creat_complete_btree(2*startno+1, endno);
    }

    return ptmpnode;
}

(3)二叉树深度优先遍历及销毁(递归实现):

前序遍历:

int preorder_btree(treenode *proot)
{
    printf("%d ", proot->no);
    if(proot->pleftchild != NULL)
    {
        preorder_btree(proot->pleftchild);
    }
    if(proot->prightchild != NULL)
    {
        preorder_btree(proot->prightchild);
    }

    return 0;
}

中序遍历:

int inorder_btree(treenode *proot)
{
    if(proot->pleftchild != NULL)
    {
        inorder_btree(proot->pleftchild);
    }
    printf("%d ", proot->no);
    if(proot->prightchild != NULL)
    {
        inorder_btree(proot->prightchild);
    }

    return 0;
}

后续遍历:

int postorder_btree(treenode *proot)
{
    if(proot->pleftchild != NULL)
    {
        postorder_btree(proot->pleftchild);
    }
    if(proot->prightchild != NULL)
    {
        postorder_btree(proot->prightchild);
    }
    printf("%d ", proot->no);

    return 0;
}

销毁:

int destory_btree(treenode *proot)
{
    if(proot->pleftchild != NULL)
    {
        destory_btree(proot->pleftchild);
    }
    if(proot->prightchild != NULL)
    {
        destory_btree(proot->prightchild);
    }
    free(proot);

    return 0;
}

(4)二叉树的广度优先遍历

通过建立链式队列不断入队、出队并打印来实现

int layoutorder_btree(treenode *proot)
{
    linknode *ptmpqueue = NULL;
    treenode *ptmpnode = NULL;
    ptmpqueue = create_empty_linkqueue();
    enter_linkqueue(ptmpqueue, proot);
    while (!is_empty_linkqueue(ptmpqueue))
    {
        ptmpnode = quit_linkqueue(ptmpqueue);
        printf("%d ", ptmpnode->no);
        if (ptmpnode->pleftchild != NULL)
        {
            enter_linkqueue(ptmpqueue, ptmpnode->pleftchild);
        }
        if (ptmpnode->prightchild != NULL)
        {
            enter_linkqueue(ptmpqueue, ptmpnode->prightchild);
        }
    }
    destroy_linkqueue(&ptmpqueue);
    return 0;
}

(5)创建非完全二叉树

非完全二叉树,每个结构不一定相同,所以需要从终端接收用户输入决定二叉树的创建

treenode *create_btree(void)
{
    char ch = 0;
    treenode *ptmpnode = NULL;
    scanf(" %c", &ch);
    if ('#' == ch)
    {
        return NULL;
    }
    ptmpnode = malloc(sizeof(treenode));
    if (NULL == ptmpnode)
    {
        perror("fail to malloc");
        return NULL;
    }
    ptmpnode->data = ch;
    ptmpnode->pleftchild = create_btree();
    ptmpnode->prightchild = create_btree();
    return ptmpnode;
}

(6) 获得树的高度、深度、层数

int get_bintree_height(treenode *proot)
{
    int leftheight = 0;
    int rightheight = 0;
    if (NULL == proot)
    {
        return 0;
    }
    leftheight = get_bintree_height(proot->pleftchild);
    rightheight = get_bintree_height(proot->prightchild);
    return (leftheight > rightheight ? leftheight : rightheight)+1;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值