【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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章