【DSA】树-二叉树接口封装(1)

github地址:https://github.com/jobbofhe/Learning_Data_Structure_and_Algorithms

/*
* @Author: jobbofhe
* @Date:   2019-07-29 20:08:30
* @Last Modified by:   Administrator
* @Last Modified time: 2019-08-07 20:11:18
*/


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

typedef int TYPE;

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

typedef struct BSTreeNode
{
    TYPE key;
    struct BSTreeNode *left;
    struct BSTreeNode *right;
    struct BSTreeNode *parent;
    
}Node, *BSTree;


Node *create_bstree_node(TYPE key, Node *parent, Node *left, Node *right);

Node *insert_bstree(BSTree tree, TYPE key);

// 前根序遍历
void pre_order_bstree(BSTree tree);

// 中根序遍历
void middle_order_bstree(BSTree tree);

// 后根序遍历
void behind_order_bstree(BSTree tree);

// 中根序
// 递归方式
// 在二叉树中,查找值为key的节点
Node *bstree_search_recursion(BSTree tree, TYPE key);
// 中根序
// 循环方式
// 在二叉树中,查找值为key的节点
Node *bstree_search(BSTree tree, TYPE key);

// 中根序,查找最大值
Node *bstree_search_max(Node *pnode);

// 中根序,朝赵最小值
Node *bstree_search_min(Node *pnode);

// 中根序,查找 某结点的前驱
Node *bstree_search_predecessor(Node *pnode);
// 中根序,查找 某结点的后继结点
Node *bstree_search_successor(Node *pnode);

// 内部接口
// 中根序 向树tree中插入一个结点,返回插入后的树的根节点
static Node *bstree_insert(BSTree tree, Node *newNode);

// 外部接口,在树中新建结点,并返回根节点
Node *create_bstree(BSTree tree, TYPE key);

// 删除节点
static Node *bstree_delete_node(BSTree tree, Node *dstNode);

// 打印整颗二叉树(tree)。其中,tree是二叉树节点,key是二叉树的键值,而direction表示该节点的类型:

// direction为 0,表示该节点是根节点;
// direction为-1,表示该节点是它的父结点的左孩子;
// direction为 1,表示该节点是它的父结点的右孩子。
void printf_bstree(BSTree tree, TYPE key, int direction);

void destroy_bstree(BSTree tree);


Node *create_bstree_node(TYPE key, Node *parent, Node *left, Node *right)
{
    Node *p = (Node*)malloc(sizeof(Node));

    if (NULL == p)
    {
        printf("Faild to malloc!\n");
        return NULL;
    }

    p->key = key;
    p->parent = parent;
    p->left = left;
    p->right = right;

    return p;
}

Node *insert_bstree(BSTree tree, TYPE key)
{
    Node * pnode = create_bstree_node(key, NULL, NULL, NULL);

    if (NULL == pnode)
    {
        printf("Faile create bstree node!\n");
        return tree;
    }

    return tree;    
}

// 前根序遍历
void pre_order_bstree(BSTree tree)
{
    if (NULL == tree)
    {
        return ;
    }

    printf("%d ", tree->key);
    pre_order_bstree(tree->left);
    pre_order_bstree(tree->right);
}

// 中根序遍历
void middle_order_bstree(BSTree tree)
{
    if (NULL == tree)
    {
        return ;
    }

    middle_order_bstree(tree->left);
    printf("%d ", tree->key);
    middle_order_bstree(tree->right);
}

// 后根序遍历
void behind_order_bstree(BSTree tree)
{
    if (NULL == tree)
    {
        return ;
    }

    behind_order_bstree(tree->left);
    behind_order_bstree(tree->right);
    printf("%d ", tree->key);
}

// 中根序
// 递归方式
// 在二叉树中,查找值为key的节点
Node *bstree_search_recursion(BSTree tree, TYPE key)
{
    if (tree == NULL || tree->key == key)
    {
        return tree;
    }

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

// 中根序
// 循环方式
// 在二叉树中,查找值为key的节点
Node *bstree_search(BSTree tree, TYPE key)
{
    if (NULL == tree)
    {
        return tree;
    }
    while(NULL != tree && (tree->key != key))
    {
        if (key < tree->key)
        {
            tree = tree->left;
        }
        else
        {
            tree = tree->right;
        }
    }

    return tree;
}

// 中根序,查找最大值
Node *bstree_search_max(Node *pnode)
{
    if (NULL == pnode)
    {
        return pnode;
    }

    while(pnode->right != NULL) 
    {
        pnode = pnode->right;
    }

    return pnode;
}

// 中根序,朝赵最小值
Node *bstree_search_min(Node *pnode)
{
    if (NULL == pnode)
    {
        return pnode;
    }

    while(pnode->left != NULL) 
    {
        pnode = pnode->left;
    }

    return pnode;
}

// 中根序,查找 某结点的前驱
Node *bstree_search_predecessor(Node *pnode)
{
    
    if (NULL == pnode)
    {
        return pnode;
    }

    // 如果 pnode 存在左孩子,则它的前驱是,以它的左孩子为根节点的子树的最大结点
    while(NULL != pnode->left) 
    {
        return bstree_search_max(pnode->left);
    }

    // 如果 pnode 没有左孩子,则有以下两种可能
    // 1) pnode 是一个右孩子,那么他的前驱就是 它的父节点
    // 2) pnode 是一个左孩子,那么 查找 pnode 的最低的 父节点,并且该父节点要具有右孩子, 找到的这个最低的父节点 就是 x的前驱节点
    Node *tmp = pnode->parent;
    while(NULL != tmp && (pnode == tmp->left)) 
    {
        pnode = tmp;
        tmp = tmp->parent;
    }

    return tmp;
}

// 中根序,查找 某结点的后继结点
Node *bstree_search_successor(Node *pnode)
{
    
    if (NULL == pnode)
    {
        return pnode;
    }

    // 如果 pnode 存在右孩子,则它的后继就是他的右孩子
    while(NULL != pnode->left) 
    {
        return bstree_search_max(pnode->left);
    }

    // 如果 pnode 没有右孩子,则有以下两种可能
    // 1) pnode 是一个左孩子,那么他后继就是 它的父节点
    // 2) pnode 是一个右孩子,那么 查找 pnode 的最低的 父节点,并且该父节点要具有左孩子, 找到的这个最低的父节点 就是 x的后继节点
    Node *tmp = pnode->parent;
    while(NULL != tmp && (pnode == tmp->left)) 
    {
        pnode = tmp;
        tmp = tmp->parent;
    }

    return tmp;
}

// 内部接口
// 中根序 向树tree中插入一个结点,返回插入后的树的根节点
static Node *bstree_insert(BSTree tree, Node *newNode)
{
    if (newNode == NULL)
    {
        return tree;
    }

    Node *pTree = tree;
    Node *pTmp = NULL;

    // 找到要插入的位置
    while(NULL != pTree) 
    {
        pTmp = pTree;
        // 新节点小于根节点
        if (newNode->key < pTree->key)
        {
            pTree = pTree->left;
        }
        else if(newNode->key > pTree->key) // 新节点大于根节点
        {
            pTree = pTree->right;
        }
        else // 新节点等于根节点
        {
            free(newNode);

            return tree;
        }
    }
    newNode->parent = pTmp;

    // 如果没有找到要插入的位置,即tree为空
    if(pTmp == NULL)
    {
        tree = newNode;
    }
    else if (newNode->key < pTmp->key)
    {
        pTmp->left = newNode;
    }
    else
    {
        pTmp->right = newNode;
    }

    return tree;
}

// 外部接口,在树中新建结点,并返回根节点
Node *create_bstree(BSTree tree, TYPE key)
{
    Node *newNode;

    // 创建新结点
    newNode = create_bstree_node(key, NULL,  NULL, NULL);
    if (NULL == newNode)
    {
        return tree;
    }

    return bstree_insert(tree, newNode);
}

// 删除节点
static Node *bstree_delete_node(BSTree tree, Node *dstNode)
{
    Node *x = NULL;
    Node *y = NULL;

    // 根据要删除的结点的类型,确定要删除的节点或者他的后继
    if (dstNode->left == NULL || dstNode->right == NULL)
    {
        y = dstNode;
    }
    else // 左右孩子都不为空
    {
        // 查找要删除的节点的 后继
        y = bstree_search_successor(dstNode);
    }

    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 != dstNode)
    {
        dstNode->key = y->key;
    }

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

    return tree;
}

// 删除值为key的节点
Node* bstree_delete_key(BSTree tree, TYPE key)
{
    Node *z, *node; 

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

    return tree;
}

// 打印整颗二叉树(tree)。其中,tree是二叉树节点,key是二叉树的键值,而direction表示该节点的类型:

// direction为 0,表示该节点是根节点;
// direction为-1,表示该节点是它的父结点的左孩子;
// direction为 1,表示该节点是它的父结点的右孩子。
void printf_bstree(BSTree tree, TYPE key, int direction)
{
    if (NULL == tree)
    {
        return;
    }

    // 根节点
    if (0 == direction) 
    {
        printf("%3d is root.\n", tree->key);
    }
    else
    {
        printf("%3d is %3d's %6s child.\n", tree->key, key, direction == 1?"right":"left");
    }

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

void destroy_bstree(BSTree tree)
{
    if (tree == NULL)
    {
        return;
    }

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

    free(tree);
}

static int arr[] = {3, 54, 6, 7, 43, 9, 59, 55, 0, 2};
int main(int argc, char const *argv[])
{
    Node *root;

    int i = 0;
    printf("--> 新建结点: ");
    for (i=0; i < 10; ++i)
    {
        printf("%d ", arr[i]);
        root = create_bstree(root, arr[i]);
    }

    printf("\n--> 前序遍历: ");
    pre_order_bstree(root);

    printf("\n--> 中序遍历: ");
    middle_order_bstree(root);

    printf("\n--> 后序遍历: ");
    behind_order_bstree(root);

    printf("\n--> 最大值: ");
    Node *max = bstree_search_max(root);
    printf(" %d", max->key);

    printf("\n--> 最小值: ");
    Node *min = bstree_search_min(root);
    printf(" %d", min->key);

    printf("\n--> 查找55节点: ");
    Node *node = bstree_search(root, 55);
    printf(" %d", node->key);

    printf("\n--> 打印二叉树:\n");
    printf_bstree(root, root->key, 0);

    bstree_delete_key(root, 55);

    printf("\n--> 最大值: ");
    max = bstree_search_max(root);
    printf(" %d", max->key);

    printf("\n--> 前序遍历: ");
    pre_order_bstree(root);
    printf("\n");

    destroy_bstree(root);

    return 0;
}
发布了134 篇原创文章 · 获赞 119 · 访问量 31万+

猜你喜欢

转载自blog.csdn.net/jobbofhe/article/details/100079555