C語言 二叉搜索樹

二叉搜索樹簡介

二叉查找樹(Binary Search Tree),(又:二叉搜索樹,二叉排序樹)它或者是一棵空樹,或者是具有下列性質的二叉樹: 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值; 它的左、右子樹也分別爲二叉排序樹。

簡而言之, 二叉樹的左子樹總是比右字數小。

二叉搜索樹的模擬過程可以看鏈接:BST

重要:在之後的關於樹的算法中,我們構建的樹將使用鏈表,而不是使用數組。所以爲了實現代碼,你需要先了解結構體和指針的一些內容。

實現過程

爲了比較容易地理解插入排序,我們可以列出一組數據,比如:
1,5,4,3,7

這裏寫圖片描述

個人分析

可以發現我們取出一個數後,再進行節點值的比較,如果比節點小,則這個數在值的左子樹,這時候,我們在進入左子樹,很顯然我們相當於又是取出一個數與一個節點比較,只不過這個時候,節點變成了之前節點的左子樹,所以我們可以用遞歸的方法構建出二叉樹。

實現過程

1 首先我們需要構建一個節點的結構體

typedef struct Bi{
    int val;
    int pos;
    int height;

    struct Bi *left_child;
    struct Bi *right_child;
} Btree, *BtreePtr;

2 然後就是構建二叉樹, 首先遍歷每個節點放入結構體中,再將結構體插入到主結構體中


    BtreePtr b = (BtreePtr)malloc(sizeof(Btree));;
    memset(b, 0, sizeof(Btree));  //將結構體中的指針初始化
    for (int i = 0; i < length; i++) {
        BtreePtr p = (BtreePtr)malloc(sizeof(Btree));
        memset(p, 0, sizeof(Btree));
        p->val = a[i];
        p->pos = i;
        p->height = 1;

        insertTree(b, p);  //構建二叉樹
    }

接下來就是插入二叉樹了,這裏是重點。

void insertTree(BtreePtr a, BtreePtr b) {
    //new value in b
    if ( a->height == 0) {
        *a = *b;  //不能用a = b
        free(b);
    }
    else {
        if (a->val < b->val) {
            if (a->right_child != NULL) {
                insertTree(a->right_child, b);
            }
            else {
                a->right_child = b;  //不能用 *(a-> right_child) = *b
            }
        }
        else {
            if (a->left_child != NULL) {
                insertTree(a->left_child, b);
            }
            else { 
                a->left_child = b; //不能用 *(a-> left_child) = *b
            }
        }
    }

    //節點高度
    if (a->left_child != NULL) {
        if (a->left_child->height == a->height) {
            (a->height)++;
        }
    }
    if (a->right_child != NULL) {
        if (a->right_child->height == a->height) {
            (a->height)++;
        }
    }
}

3 最後,是在二叉樹中搜索,這裏很簡單,就不提示了。

完整代碼:

#include <stdio.h>
#include <malloc.h>
#include <memory.h>

typedef struct Bi{
    int val;
    int pos;
    int height;

    struct Bi *left_child;
    struct Bi *right_child;
} Btree, *BtreePtr;

void insertTree(BtreePtr a, BtreePtr b) {
    //new value in b
    if ( a->height == 0) {
        *a = *b;  //不能用a = b, 這一步相當於將b中的所有數據都copy到a
        free(b); //之後b不需要了 ,所以需要釋放b
    }
    else {
        if (a->val < b->val) {
            if (a->right_child != NULL) {
                insertTree(a->right_child, b);
            }
            else {
                a->right_child = b;  //不能用 *(a-> right_child) = *b
            }
        }
        else {
            if (a->left_child != NULL) {
                insertTree(a->left_child, b);
            }
            else { 
                a->left_child = b; //不能用 *(a-> left_child) = *b
            }
        }
    }

    if (a->left_child != NULL) {
        if (a->left_child->height == a->height) {
            (a->height)++;
        }
    }
    if (a->right_child != NULL) {
        if (a->right_child->height == a->height) {
            (a->height)++;
        }
    }
}

int midSearch(const BtreePtr a, const int key) {
    if (a != NULL) {
        if (key > a->val) {
            return midSearch(a->right_child, key);
        }
        else if(key < a->val) {
            return midSearch(a->left_child, key);
        }
        else {
            return a->pos;
        }
    }
    else {
        return -1;
    }
}

void freeTree(BtreePtr b) {
    if (b->right_child !=NULL) {
        freeTree(b->right_child);
    }
    if (b->left_child != NULL) {
        freeTree(b->left_child);
    }
}

int binaryTreeSearch(const int *a, const int length, const int key) {
    BtreePtr b = (BtreePtr)malloc(sizeof(Btree));;
    memset(b, 0, sizeof(Btree));  //將結構體中的指針初始化
    for (int i = 0; i < length; i++) {
        BtreePtr p = (BtreePtr)malloc(sizeof(Btree));
        memset(p, 0, sizeof(Btree));
        p->val = a[i];
        p->pos = i;
        p->height = 1;

        insertTree(b, p);  //構建二叉樹
    }
    int pos = midSearch(b, key);
    freeTree(b); //不能直接使用free(b)
    return pos;
}


void main() {
    const int length = 5;
    int my_array[5] = { 1 ,7, 6, 8, 0 };

    printf("%d \n", binaryTreeSearch(my_array, length, 6));
}
發佈了33 篇原創文章 · 獲贊 13 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章