树与二叉树

树与二叉树

基本概念

树是一种非线性结构,一组数据中除了第一个节点,任意节点有且仅有一个直接前驱,有零哥=个或多个直接后驱,该组数据形成了一棵树,为一对多的数据关系。

基本术语

树的第一个节点,没有直接前驱。

双亲结点

某节点的直接前驱节点称为该节点的双亲节点。

孩子节点

某节点的直接后继节点称为孩子节点。

节点的层次

根节点点所在节点规定为第一层,其孩子所在层次称为第二层,以此类推。

节点的度

一个节点拥有的孩子节点的总数,称为该节点的度。

叶子

一棵树中结点的度等于0的节点,称为叶子,又叫终端节点。

树的高度

一棵树中所有节点的层次的最大值,称为这棵树的高度,又叫深度。

有序树与无序树

一棵树中,如果某个节点孩子节点之间是有序的(不可进行交换),称为有序树,否则为无序树。

二叉树

二叉树概念:

1.有序树

2.任意节点的度小于等于2(一个节点最多两个孩子)

二叉树基本特性

1.第I层上,最多有2^(i-1)个节点

2.高度为k的二叉树,最多有2^(k-1)个节点。

3.叶子数目为n0,度为2的的节点的节点数目为n2。则有n0=n2+1。

满二叉树/完美二叉树:

高度为K的树,节点总数为2^k-1.

完全二叉树:

节点标号连续(从上到下,从左到右)

平衡二叉树:

任意节点的两棵子树高度差小于一。

退化二叉树:

所有节点的度小于等于1,退化为链表。

二叉树的链式存储

typedef struct node
{
    datatype data; // 用户数据  数据域

    struct node *lchild; // 左孩子树指针
    struct node *rchild; // 右孩子树指针
}node;

树的遍历

前序遍历(根---左---右)、中序遍历(左--根---右)、后序遍历(左---右---根)。

按层遍历:从上到下,从左到右依次访问节点

前中后序遍历都是递归算法。

BST树

基本概念

搜索二叉树/二叉排序树/二叉查找树:将数据节点按照某种规律形成的一颗二叉树

提高搜索效率:小中大的归率存储/大中小

插入节点

// 假设 BST 节点存储的数据类型是 int
node *newNode(int data)
{
    // 准备好新节点,并将数据填入其中
    node *new = (node *)malloc(sizeof(node));
    if(new != NULL)
    {
        new->data = data;
        new->lchild = NULL;
        new->rchild = NULL;
    }
    return new;
}
// 将新节点new插入到一棵以 root 为根的 BST 中
// 插入节点后,返回新的 BST 的根
node *bstInsert(node *root, node *new)
{
    // 若此时 BST 为空,则返回 new 使之成为二叉树的根节点
    if(root == NULL)
        return new;

    // 若新节点比根节点小,那么新节点应该插入左子树中
    // 至于插入到左子树的具体什么位置就不用管了,直接递归即可
    if(new->data < root->data)
        root->lchild = bstInsert(root->lchild, new);

    // 若新节点比根节点大,那么新节点应该插入右子树中,直接递归即可
    else if(new->data > root->data)
        root->rchild = bstInsert(root->rchild, new);

    // 若已存在,则不处理  数据不允许相同
    else
    {
        printf("%d已存在\n", new->data);
        free(new);
    }

    return root;
}

删除节点

// 将数据(以整型为例)data从二叉树中删除
// 并返回删除之后的二叉树的根
node *bstRemove(node *root, int data)
{
    node *tmp = NULL;
    
    if(root == NULL)
        return NULL;

    // 若data小于根节点,则递归地在左子树中删除它
    if(data < root->data)
        root->lchild = bstRemove(root->lchild, data);

    // 若data小于根节点,则递归地在左子树中删除它
    else if(data > root->data)
        root->rchild = bstRemove(root->rchild, data);

    //找到相同的数据 
    else
    {
        // a. 根节点若有左子树,则用左子树中最大的节点max替换根节点
        //    并在左子树中递归删除max  
        if(root->lchild != NULL)
        {
            node *max;
            for(max=root->lchild; max->rchild!=NULL;
                max=max->rchild);

            root->data = max->data;
            root->lchild = bstRemove(root->lchild, max->data);
        }

        // b. 否则,若有右子树,则用右子树中最小的节点min替换根节点
        //    并在右子树中递归删除min  
        else if(root->rchild != NULL)
        {
            for(tmp=root->rchild; tmp->lchild!=NULL;
                tmp=tmp->lchild);

            root->data = tmp->data;
            root->rchild = bst_remove(root->rchild, tmp->data);
        }

        // c. 否则,直接删除节点
        else
        {
            free(root);
            return NULL;
        }
    }

    return root;
}

遍历代码

// 前序遍历
void preOrder(node *root)
{
    if(root == NULL)
        return;

    // 先访问根节点
    printf("%d", root->data);

    // 再依次使用前序算法,遍历其左、右子树
    preOrder(root->lchild);
    preOrder(root->rchild);
}

// 中序遍历
void inOrder(node *root)
{
    if(root == NULL)
        return;

    // 先访问左子树
    inOrder(root->lchild);

    // 再访问根节点
    printf("%d", root->data);

    // 再访问右子树
    inOrder(root->rchild);
}

// 后序遍历
void postOrder(node *root)
{
    if(root == NULL)
        return;

    // 先依次使用后序算法,遍历其左、右子树
    postOrder(root->lchild);
    postOrder(root->rchild);

    // 再访问根节点
    printf("%d", root->data);
}
posted @ 2024-07-17 21:40  do泽  阅读(3)  评论(0编辑  收藏  举报