C語言實現(xiàn)常用數(shù)據(jù)結(jié)構(gòu)(二)

二叉排序樹實現(xiàn)

1、二叉排序樹饿自,也叫二叉搜索樹圾亏,中序遍歷為有序序列。這是一種特殊的二叉樹叙身,每個節(jié)點(diǎn)的左孩子都比其要小渔扎,右孩子都比其要大,二叉樹的所有子樹也都是二叉搜索樹信轿。

2晃痴、二叉排序樹主要功能實現(xiàn):構(gòu)造二叉樹、插入節(jié)點(diǎn)财忽、刪除節(jié)點(diǎn)倘核。

2.1、插入節(jié)點(diǎn):二叉排序樹是一個有序序列即彪,插入節(jié)點(diǎn)時只需要從根節(jié)點(diǎn)開始查詢紧唱,如果要插入的節(jié)點(diǎn)數(shù)據(jù)比該節(jié)點(diǎn)小,則進(jìn)入其左孩子位置隶校,如比其大漏益,則進(jìn)入其右孩子位置,一直找到空閑位置為止深胳。

2.2绰疤、刪除節(jié)點(diǎn):這里有三種情況,一種是刪除葉子節(jié)點(diǎn)舞终,一種是刪除根節(jié)點(diǎn)轻庆,一種是刪除中間節(jié)點(diǎn)癣猾。
刪除葉子節(jié)點(diǎn)時只需要將葉子節(jié)點(diǎn)置NULL即可;刪除根節(jié)點(diǎn)需要將其左孩子設(shè)為新的根節(jié)點(diǎn)余爆,如果左孩子不存在則將右孩子設(shè)為新的根節(jié)點(diǎn)纷宇;刪除中間節(jié)點(diǎn)需要將其父節(jié)點(diǎn)和其子節(jié)點(diǎn)先連接起來,具體實現(xiàn)可查看下文龙屉。

C語言實現(xiàn)常用數(shù)據(jù)結(jié)構(gòu)(一)

樹節(jié)點(diǎn)定義
b_tree_node.h

#pragma once
#ifndef BinaryTreeNode

#include <stdlib.h>
typedef struct BinaryTreeNode
{
    void* data;
    struct BinaryTreeNode* left_node;
    struct BinaryTreeNode* right_node;
    struct BinaryTreeNode* parent_node;
}b_tree_node;

b_tree_node* create_tree_node(void* data);

b_tree_node* append_left_node_data(b_tree_node* node, void* data);
b_tree_node* append_left_node(b_tree_node* node, b_tree_node* new_node);

b_tree_node* append_right_node_data(b_tree_node* node, void* data);
b_tree_node* append_right_node(b_tree_node* node, b_tree_node* new_node);

#endif

b_tree_node.c

#include "b_tree_node.h"

b_tree_node * create_tree_node(void * data)
{
    b_tree_node *new_node = malloc(sizeof(b_tree_node));
    new_node->data = data;
    new_node->left_node = NULL;
    new_node->right_node = NULL;
    new_node->parent_node = NULL;

    return new_node;
};

b_tree_node* append_left_node_data(b_tree_node* node, void* data)
{
    b_tree_node *newNode = create_tree_node(data, node);
    node->left_node = newNode;
    newNode->parent_node = node;

    return newNode;
};

b_tree_node * append_left_node(b_tree_node * node, b_tree_node * new_node)
{
    node->left_node = new_node;
    new_node->parent_node = node;

    return new_node;
};

b_tree_node* append_right_node_data(b_tree_node* node, void* data)
{
    b_tree_node *newNode = create_tree_node(data);
    node->right_node = newNode;
    newNode->parent_node = node;

    return newNode;
};

b_tree_node* append_right_node(b_tree_node* node, b_tree_node* new_node)
{
    node->right_node = new_node;
    new_node->parent_node = node;

    return new_node;
}

二叉樹定義
binary_tree.h

#pragma once
#ifndef BinaryTree

#include <stdlib.h>
#include "m_queue.h"
#include "m_stack.h"
#include "b_tree_node.h"
#include <cstdbool>

typedef struct BinaryTree
{
    b_tree_node* root;
}b_tree, b_tree_bst;

b_tree* create_b_tree();
b_tree* create_b_tree_root(void* data);
b_tree* create_b_tree_level(void* list[], int len); //層序創(chuàng)建二叉樹

b_tree_bst* create_bst_tree(void* list[], int len); //創(chuàng)建二叉排序樹呐粘,中序遍歷為順序排列
void insert_node_by_bst(b_tree_bst *bst_tree, b_tree_node *node);   //排序樹插入節(jié)點(diǎn)
void insert_node_data_by_bst(b_tree_bst *bst_tree, void *data); //排序樹插入節(jié)點(diǎn)數(shù)據(jù)
b_tree_node* find_node_by_bst(b_tree_bst *bst_tree, void *data);        //從排序樹從找到第一個等于data的節(jié)點(diǎn)
void destroy_node_data_by_bst(b_tree_bst *bst_tree, void* data);        //排序樹刪除節(jié)點(diǎn)

void dispose_b_tree(b_tree ** tree);  //釋放

void PreOrder(b_tree_node * root_node);
void PreOrder2(b_tree* tree);
void Inorder(b_tree_node * root_node);
void Inorder2(b_tree* tree);
void LastOrder(b_tree_node * root_node);
void LevelOrder(b_tree* tree);
#endif

binary_tree.c

#include "binary_tree.h"

b_tree * create_b_tree()
{
    b_tree *tree = malloc(sizeof(b_tree));
    tree->root = NULL;
    return tree;
};

b_tree* create_b_tree_root(void* data)
{
    b_tree* tree = create_b_tree();
    b_tree_node  *node = create_tree_node(data);
    tree->root = node;
    return tree;
};

b_tree * create_b_tree_level(void* list[], int len)
{
    if (len == 0)
    {
        perror("create binary tree by level,len==0");
        return NULL;
    }

    b_tree *tree = create_b_tree_root(list[0]);
    m_queue *queue = init_queue();
    en_queue_data(queue, tree->root);
    int index = 1;  //當(dāng)前未插入數(shù)據(jù)索引

    while (queue->len > 0)
    {
        b_tree_node *tree_node = de_queue_data(queue);

        if (index < len)
        {
            append_left_node_data(tree_node, list[index]);
            index++;
            en_queue_data(queue, tree_node->left_node);
        }
        if (index < len)
        {
            append_right_node_data(tree_node, list[index]);
            index++;
            en_queue_data(queue, tree_node->right_node);
        }
    }

    dispose_que(&queue);
    return tree;
};

b_tree_bst * create_bst_tree(void* list[], int len)
{
    b_tree_bst* tree_bst = create_b_tree_root(list[0]);
    for (int i = 1; i < len; i++)
    {
        insert_node_data_by_bst(tree_bst, list[i]);
    }

    return tree_bst;
};

void insert_node_by_bst(b_tree_bst * bst_tree, b_tree_node * node)
{
    if (bst_tree->root == NULL)
    {
        bst_tree->root = node;
        return;
    }

    b_tree_node *temp = bst_tree->root;
    while (temp != NULL)
    {
        if (node->data <= temp->data)   //插入節(jié)點(diǎn)比對比節(jié)點(diǎn)數(shù)據(jù)小,進(jìn)入左節(jié)點(diǎn)比較
        {
            if (temp->left_node == NULL)    //找到空余位置
            {
                append_left_node(temp, node);
                return;
            }
            else
            {
                temp = temp->left_node;
            }

        }
        else
        {
            if (temp->right_node==NULL)
            {
                append_right_node(temp, node);
                return;
            }
            else
            {
                temp = temp->right_node;
            }

        }
    }
};

void insert_node_data_by_bst(b_tree_bst * bst_tree, void * data)
{
    b_tree_node *tree_node = create_tree_node(data);
    insert_node_by_bst(bst_tree, tree_node);
};

b_tree_node* find_node_by_bst(b_tree_bst *bst_tree, void *data)
{
    if (bst_tree->root == NULL)
    {
        perror("bst tree find node,root is null\n");
        return NULL;
    }

    b_tree_node *temp = bst_tree->root;
    while (temp != NULL)
    {
        if (data == temp->data)
        {
            return temp;
        }
        if (data <= temp->data)
        {
            temp = temp->left_node;
        }
        else
        {
            temp = temp->right_node;
        }
    }

    return NULL;
}

void destroy_node_data_by_bst(b_tree_bst *bst_tree, void* data)
{
    b_tree_node *tree_node = find_node_by_bst(bst_tree, data);
    if (tree_node == NULL)
    {
        return;
    }

    b_tree_node *left_node = tree_node->left_node;
    b_tree_node *right_node = tree_node->right_node;
    b_tree_node *parent_node = tree_node->parent_node;

    if (tree_node == bst_tree->root)    //刪除根節(jié)點(diǎn)
    {
        if (left_node != NULL)
        {
            bst_tree->root = left_node;     //左節(jié)點(diǎn)成為新的根節(jié)點(diǎn)
            bst_tree->root->parent_node = NULL;

            if (right_node != NULL) //右節(jié)點(diǎn)不為null转捕,重新尋找位置
            {
                insert_node_by_bst(bst_tree, right_node);
            }
        }
        else
        {
            bst_tree->root = right_node;
            bst_tree->root->parent_node = NULL;
        }
        free(tree_node);
        return;
    }

    bool tree_node_parent_left = tree_node->parent_node->left_node == tree_node;    //待刪除節(jié)點(diǎn)處于父節(jié)點(diǎn)左子樹作岖?
    if (left_node == NULL && right_node == NULL)    //刪除葉子節(jié)點(diǎn)
    {
        if (tree_node_parent_left)
        {
            tree_node->parent_node->left_node = NULL;
        }
        else
        {
            tree_node->parent_node->right_node = NULL;
        }
    }
    else
    {
        b_tree_node *new_node = left_node ? left_node : right_node;
        new_node->parent_node = parent_node;

        if (tree_node_parent_left)
        {
            parent_node->left_node = new_node;
        }
        else
        {
            parent_node->right_node = new_node;
        }

        if (left_node != NULL && right_node != NULL)    //刪除的節(jié)點(diǎn)右子節(jié)點(diǎn)不為null,需要附加到之前的左節(jié)點(diǎn)右邊
        {
            insert_node_by_bst(bst_tree, right_node);
        }
    }

    free(tree_node);
};

void dispose_b_tree(b_tree ** tree)
{
    if ((*tree)->root==NULL)
    {
        return;
    }

    m_stack *stack = init_stack();
    m_queue *queue = init_queue();
    en_queue_data(queue, (*tree)->root);

    while (queue->len>0)
    {
        b_tree_node *tree_node = de_queue_data(queue);
        if (tree_node->left_node != NULL)
        {
            en_queue_data(queue, tree_node->left_node);
        }
        if (tree_node->right_node!=NULL)
        {
            en_queue_data(queue, tree_node->right_node);
        }

        push_node_data_stack(stack, tree_node);
    }

    while (stack->len > 0)
    {
        b_tree_node *tree_node = pop_data_stack(stack);
        free(tree_node);
    }

    dispose_stack(&stack);
    dispose_que(&queue);

    free(*tree);
    *tree = NULL;
};

void PreOrder(b_tree_node * root_node)
{
    if (root_node == NULL)
    {
        return;
    }

    printf("%d\n", root_node->data);
    PreOrder(root_node->left_node);
    PreOrder(root_node->right_node);
};

void PreOrder2(b_tree* tree)
{
    if (tree->root == NULL)
    {
        return;
    }

    m_stack *stack = init_stack();
    push_node_data_stack(stack, tree->root);

    while (stack->len > 0)
    {
        b_tree_node *tree_node = pop_data_stack(stack);
        printf("%d\n", tree_node->data);

        if (tree_node->right_node != NULL)
        {
            push_node_data_stack(stack, tree_node->right_node);
        }
        if (tree_node->left_node != NULL)
        {
            push_node_data_stack(stack, tree_node->left_node);
        }
    }

    dispose_stack(&stack);
};

void Inorder(b_tree_node * root_node)
{
    if (root_node ==NULL)
    {
        return;
    }

    Inorder(root_node->left_node);
    printf("%d\n", root_node->data);
    Inorder(root_node->right_node);
};

void LastOrder(b_tree_node * root_node)
{
    if (root_node == NULL)
    {
        return;
    }

    LastOrder(root_node->left_node);
    LastOrder(root_node->right_node);
    printf("%d\n", root_node->data);
}

void LevelOrder(b_tree * tree)
{
    if (tree->root == NULL)
    {
        perror("level order, tree root is null");
        return;
    }

    m_queue *queue = init_queue();
    en_queue_data(queue, tree->root);
    
    while (queue->len > 0)
    {
        b_tree_node *tree_node = de_queue_data(queue);
        printf("%d\n", tree_node->data);

        if (tree_node->left_node != NULL)
        {
            en_queue_data(queue, tree_node->left_node);
        }
        if (tree_node->right_node != NULL)
        {
            en_queue_data(queue, tree_node->right_node);
        }
        free(tree_node);
    }

    dispose_que(&queue);
}

測試使用

#include "binary_tree.h"
void TestBinaryTree()
{
    //b_tree* tree = create_b_tree_root(1);
    //b_tree_node *a = append_left_node(tree->root, 2);
    //append_right_node(tree->root, 3);
    ////Inorder(tree->root);
    //LevelOrder(tree);

    int list[] = {9,3,1,2,11,10,12};
    //b_tree *tree = create_b_tree_level(list, array_len(list));    //層序創(chuàng)建二叉樹
    //LevelOrder(tree);

    b_tree_bst *bst_tree = create_bst_tree(list, array_len(list));
    destroy_node_data_by_bst(bst_tree, 11);
    destroy_node_data_by_bst(bst_tree, 12);
    destroy_node_data_by_bst(bst_tree, 10);

    Inorder(bst_tree->root);

    dispose_b_tree(&bst_tree);
}

int main()
{
TestBinaryTree();
return 0;
}

C語言實現(xiàn)常用數(shù)據(jù)結(jié)構(gòu)(一)
二叉排序樹在極端情況下(例如所有數(shù)據(jù)都比根節(jié)點(diǎn)大)會退化成鏈表五芝,為解決這個問題引入了平衡二叉樹痘儡。平衡二叉樹的特點(diǎn)是左右兩個子樹的高度差不能大于1,所以在插入和刪除節(jié)點(diǎn)時需要動態(tài)調(diào)整樹結(jié)構(gòu)枢步,平衡二叉樹的重點(diǎn)是旋轉(zhuǎn)算法沉删,常見實現(xiàn)方式有AVL樹,紅黑樹等醉途。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末矾瑰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子隘擎,更是在濱河造成了極大的恐慌殴穴,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件货葬,死亡現(xiàn)場離奇詭異采幌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)震桶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門休傍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蹲姐,你說我怎么就攤上這事磨取。” “怎么了淤堵?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵寝衫,是天一觀的道長。 經(jīng)常有香客問我拐邪,道長慰毅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任扎阶,我火速辦了婚禮汹胃,結(jié)果婚禮上婶芭,老公的妹妹穿的比我還像新娘。我一直安慰自己着饥,他們只是感情好犀农,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宰掉,像睡著了一般呵哨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上轨奄,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天孟害,我揣著相機(jī)與錄音,去河邊找鬼挪拟。 笑死挨务,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的玉组。 我是一名探鬼主播谎柄,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼惯雳!你這毒婦竟也來了朝巫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤石景,失蹤者是張志新(化名)和其女友劉穎捍歪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸵钝,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年庐镐,在試婚紗的時候發(fā)現(xiàn)自己被綠了恩商。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡必逆,死狀恐怖怠堪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情名眉,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布损拢,位于F島的核電站陌粹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏福压。R本人自食惡果不足惜掏秩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一或舞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蒙幻,春花似錦映凳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至抒和,卻和暖如春矫渔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背构诚。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工蚌斩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人范嘱。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓送膳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親丑蛤。 傳聞我的和親對象是個殘疾皇子叠聋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容