二叉搜索树

#include<stdio.h>
#include<stdlib.h>
#include<string.h>



static int arr[]= {1,5,4,3,2,6};
#define TBL_SIZE(a) ( (sizeof(a)) / (sizeof(a[0])) )

/*
二叉查找树的节点包含的基本信息:
(01) key        -- 它是关键字,是用来对二叉查找树的节点进行排序的。
(02) left       -- 它指向当前节点的左孩子。
(03) right      -- 它指向当前节点的右孩子。
(04) parent     -- 它指向当前节点的父结点。
*/
typedef struct treeNode
{
    int key;
    struct treeNode *left;
    struct treeNode *right;
    struct treeNode *parent;
}treeNode_t;

treeNode_t* creat_tree(int key, treeNode_t *left, treeNode_t *right, treeNode_t *parent)
{
    treeNode_t* pnode = malloc(sizeof(treeNode_t));
    
    if (pnode)
    {
        pnode->key    = key;
        pnode->left   = left;
        pnode->right  = right;
        pnode->parent = parent;
        return pnode;
    }
    return NULL;
}

/* 
前序遍历
若二叉树非空,则执行以下操作:
(01) 访问根结点;
(02) 先序遍历左子树;
(03) 先序遍历右子树。
*/
void preorder_bstree(treeNode_t *tree)
{
    if(tree != NULL)
    {
        printf("%d ", tree->key);
        preorder_bstree(tree->left);
        preorder_bstree(tree->right);
    }
}

/*
中序遍历
若二叉树非空,则执行以下操作:
(01) 中序遍历左子树;
(02) 访问根结点;
(03) 中序遍历右子树。
*/
void inorder_bstree(treeNode_t *tree)
{
    if(tree != NULL)
    {
        inorder_bstree(tree->left);
        printf("%d ", tree->key);
        inorder_bstree(tree->right);
    }
}

/*
后序遍历
若二叉树非空,则执行以下操作:
(01) 后序遍历左子树;
(02) 后序遍历右子树;
(03) 访问根结点。
*/
void postorder_bstree(treeNode_t *tree)
{
    if(tree != NULL)
    {
        postorder_bstree(tree->left);
        postorder_bstree(tree->right);
        printf("%d ", tree->key);
    }
}
/*
递归查找
*/
treeNode_t* bstree_search(treeNode_t *x, int key)
{
    if (x==NULL || x->key==key)
        return x;

    if (key < x->key)
        return bstree_search(x->left, key);
    else
        return bstree_search(x->right, key);
}

/*
查找
*/
treeNode_t* iterative_bstree_search(treeNode_t *x, int key)
{
    while ((x!=NULL) && (x->key!=key))
    {
        if (key < x->key)
            x = x->left;
        else
            x = x->right;
    }

    return x;
}

/*
最大值查找
*/
treeNode_t* bstree_maximum(treeNode_t *tree)
{
    if (tree == NULL)
        return NULL;

    while(tree->right != NULL)
        tree = tree->right;
    return tree;
}

/*
最小值查找
*/
treeNode_t* bstree_minimum(treeNode_t *tree)
{
    if (tree == NULL)
        return NULL;

    while(tree->left != NULL)
        tree = tree->left;
    return tree;
}
/*
节点的前驱:是该节点的左子树中的最大节点。
节点的后继:是该节点的右子树中的最小节点。
*/
treeNode_t* bstree_predecessor(treeNode_t *x)
{
    // 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。
    if (x->left != NULL)
        return bstree_maximum(x->left);

    // 如果x没有左孩子。则x有以下两种可能:
    // (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。
    // (01) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。
    treeNode_t* y = x->parent;
    while ((y!=NULL) && (x==y->left))
    {
        x = y;
        y = y->parent;
    }

    return y;
}

treeNode_t* bstree_successor(treeNode_t *x)
{
    // 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。
    if (x->right != NULL)
        return bstree_minimum(x->right);

    // 如果x没有右孩子。则x有以下两种可能:
    // (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。
    // (02) x是"一个右孩子",则查找"x的最低的父结点,并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。
    treeNode_t* y = x->parent;
    while ((y!=NULL) && (x==y->right))
    {
        x = y;
        y = y->parent;
    }

    return y;
}

static treeNode_t* bstree_insert(treeNode_t *tree, treeNode_t *z)
{
    treeNode_t *y = NULL;
    treeNode_t *x = tree;

    // 查找z的插入位置
    while (x != NULL)
    {
        y = x;
#if 1
//允许相同key
        if (z->key < x->key)
            x = x->left;
        else
            x = x->right;
#else
        if (z->key < x->key)
            x = x->left;
        else  if (z->key > x->key)
            x = x->right;
        else
        {
            free(z); // 释放之前分配的系统。
            return tree;
        }
#endif
    }

    z->parent = y;
    if (y==NULL)
        tree = z;
    else if (z->key < y->key)
        y->left = z;
    else
        y->right = z;

    return tree;
}

treeNode_t* insert_bstree(treeNode_t *tree, int key)
{
    treeNode_t *z;    // 新建结点

    // 如果新建结点失败,则返回。
    if ((z=creat_tree(key, NULL, NULL, NULL)) == NULL)
        return tree;

    return bstree_insert(tree, z);
}

static treeNode_t* bstree_delete(treeNode_t *tree, treeNode_t *z)
{
    treeNode_t *x=NULL;
    treeNode_t *y=NULL;

    if ((z->left == NULL) || (z->right == NULL))
        y = z;
    else
        y = bstree_successor(z);

    if (y->left != NULL)
        x = y->left;
    else
        x = y->right;

    if (x != NULL)
        x->parent = y->parent;

    if (y->parent == NULL)
        tree = x;
    else if (y == y->parent->left)
        y->parent->left = x;
    else
        y->parent->right = x;

    if (y != z) 
        z->key = y->key;

    if (y!=NULL)
        free(y);

    return tree;
}

treeNode_t* delete_bstree(treeNode_t *tree, int key)
{
    treeNode_t *z, *node; 

    if ((z = bstree_search(tree, key)) != NULL)
        tree = bstree_delete(tree, z);

    return tree;
}

void print_bstree(treeNode_t *tree, int key, int direction)
{
    if(tree != NULL)
    {
        if(direction==0)    // tree是根节点
            printf("%2d is root\n", tree->key);
        else                // tree是分支节点
            printf("%2d is %2d's %6s child\n", tree->key, key, direction==1?"right" : "left");

        print_bstree(tree->left, tree->key, -1);
        print_bstree(tree->right,tree->key,  1);
    }
}

void destroy_bstree(treeNode_t *tree)
{
    if (tree==NULL)
        return ;

    if (tree->left != NULL)
        destroy_bstree(tree->left);
    if (tree->right != NULL)
        destroy_bstree(tree->right);

    free(tree);
}


int main(int argc, char*argv[])
{

    int i, ilen;
    treeNode_t * root=NULL;

    printf("== 依次添加: ");
    ilen = TBL_SIZE(arr);
    for(i=0; i<ilen; i++)
    {
        printf("%d ", arr[i]);
        root = insert_bstree(root, arr[i]);
    }

    printf("\n== 前序遍历: ");
    preorder_bstree(root);

    printf("\n== 中序遍历: ");
    inorder_bstree(root);

    printf("\n== 后序遍历: ");
    postorder_bstree(root);
    printf("\n");

    printf("== 最小值: %d\n", bstree_minimum(root)->key);
    printf("== 最大值: %d\n", bstree_maximum(root)->key);
    printf("== 树的详细信息: \n");
    print_bstree(root, root->key, 0);

    printf("\n== 删除根节点: %d", arr[3]);
    root = delete_bstree(root, arr[3]);

    printf("\n== 中序遍历: ");
    inorder_bstree(root);
    printf("\n");

    // 销毁二叉树
    destroy_bstree(root);

    return 1;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值