二叉排序树(Binary Sort Tree) 又称为二叉查找树(Binary Search Tree) - (代码、分析)

目录:

代码:

BSTree.h

#ifndef _BSTREE_H_
#define _BSTREE_H_

typedef void BSTree;//定义二叉树类型
typedef void BSKey;//定义节点的键值类型(用于节点排序)

typedef struct _tag_BSTreeNode BSTreeNode;//定义二叉树节点类型
struct _tag_BSTreeNode
{
    
    
    BSKey* key;//键值
    BSTreeNode* left;//左子节点
    BSTreeNode* right;//右子节点
};

typedef void (BSTree_Printf)(BSTreeNode*);//定义参数为一个节点指针并且无返回值的函数类型
typedef int (BSTree_Compare)(BSKey*, BSKey*);//定义参数为两个键值指针并且无返回值的函数类型

BSTree* BSTree_Create();//声明创建树函数

void BSTree_Destroy(BSTree* tree);//声明销毁树函数

void BSTree_Clear(BSTree* tree);//声明清空树函数

int BSTree_Insert(BSTree* tree, BSTreeNode* node, BSTree_Compare* compare);//声明插入节点函数

BSTreeNode* BSTree_Delete(BSTree* tree, BSKey* key, BSTree_Compare* compare);//声明删除节点函数

BSTreeNode* BSTree_Get(BSTree* tree, BSKey* key, BSTree_Compare* compare);//声明获取节点函数

BSTreeNode* BSTree_Root(BSTree* tree);//声明获取根节点函数

int BSTree_Height(BSTree* tree);//声明获取树高度函数

int BSTree_Count(BSTree* tree);//声明获取节点数量函数

int BSTree_Degree(BSTree* tree);//声明获取树度数函数

void BSTree_Display(BSTree* tree, BSTree_Printf* pFunc, int gap, char div);//定义统一用函数处理节点函数

#endif


BSTree.c

#include <stdio.h>
#include <malloc.h>
#include "BSTree.h"

typedef struct _tag_BSTree TBSTree;//定义实际使用二叉树类型
struct _tag_BSTree
{
    
    
    int count;//数量
    BSTreeNode* root;//根节点
};
//用递归调用函数处理节点函数
static void recursive_display(BSTreeNode* node, BSTree_Printf* pFunc, int format, int gap, char div) // O(n)
{
    
    
    int i = 0;
    
    if( (node != NULL) && (pFunc != NULL) )
    {
    
    
        for(i=0; i<format; i++)
        {
    
    
            printf("%c", div);
        }
        
        pFunc(node);
        
        printf("\n");
        
        if( (node->left != NULL) || (node->right != NULL) )
        {
    
    
            recursive_display(node->left, pFunc, format + gap, gap, div);
            recursive_display(node->right, pFunc, format + gap, gap, div);
        }
    }
    else
    {
    
    
        for(i=0; i<format; i++)
        {
    
    
            printf("%c", div);
        }
        printf("\n");
    }
}

static int recursive_count(BSTreeNode* root) //递归计算节点数量函数(没使用到)
{
    
    
    int ret = 0;
    
    if( root != NULL )
    {
    
    
        ret = recursive_count(root->left) + 1 + recursive_count(root->right);
    }
    
    return ret;
}

static int recursive_height(BSTreeNode* root) // 递归计算高度函数
{
    
    
    int ret = 0;
    
    if( root != NULL )
    {
    
    
        int lh = recursive_height(root->left);
        int rh = recursive_height(root->right);
        
        ret = ((lh > rh) ? lh : rh) + 1;
    }
    
    return ret;
}

static int recursive_degree(BSTreeNode* root) //递归计算度数函数
{
    
    
    int ret = 0;
    
    if( root != NULL )
    {
    
    
        if( root->left != NULL )
        {
    
    
            ret++;
        }
        
        if( root->right != NULL )
        {
    
    
            ret++;
        }
        
        if( ret == 1 )
        {
    
    
            int ld = recursive_degree(root->left);
            int rd = recursive_degree(root->right);
            
            if( ret < ld )
            {
    
    
                ret = ld;
            }
            
            if( ret < rd )
            {
    
    
                ret = rd;
            }
        }
    }
    
    return ret;
}

static int recursive_insert(BSTreeNode* root, BSTreeNode* node, BSTree_Compare* compare)
{
    
    
    int ret = 1;
    int r = compare(node->key, root->key);//1参数小于2参数返回负数,大于返回正数,等于返回0
    
    if( r == 0 )//如果两个键相等插入结果等于0返回到调用函数,表示插入失败
    {
    
    
        ret = 0;
    }
    else if( r < 0 )//如果插入节点的键小于当前比较的节点的键,表示应该是往当前比较的节点的左子节点走
    {
    
    
        if( root->left != NULL )//如果当前比较的节点的左子节点不为空
        {
    
    
			//将其左子节点作为下一个与插入节点比较的节点再调用函数进栈,是否插入成功结果返回这里
            ret = recursive_insert(root->left, node, compare);
        }
        else
        {
    
    
			//否则直接将插入节点作为当前比较节点的左子节点
            root->left = node;
        }
    }
    else if( r > 0 )//如果插入节点的键小于当前比较根节点的键,表示应该是往当前比较根节点的右子节点走
    {
    
    
        if( root->right != NULL )//如果当前比较的节点的右子节点不为空
        {
    
    
			//将其右子节点作为下一个与插入节点比较的节点再调用函数进栈,是否插入成功结果返回这里
            ret = recursive_insert(root->right, node, compare);
        }
        else
        {
    
    
			//否则直接将插入节点作为当前比较节点的右子节点
            root->right = node;
        }
    }
	return ret;//将结果返回
}

static BSTreeNode* recursive_get(BSTreeNode* root, BSKey* key, BSTree_Compare* compare)//递归查找节点函数
{
    
    
    BSTreeNode* ret = NULL;
    
    if( root != NULL )
    {
    
    
        int r = compare(key, root->key);
        
        if( r == 0 )
        {
    
    
            ret = root;
        }
        else if( r < 0 )
        {
    
    
            ret = recursive_get(root->left, key, compare);
        }
        else if( r > 0 )
        {
    
    
            ret = recursive_get(root->right, key, compare);
        }
    }
    
    return ret;
}

static BSTreeNode* delete_node(BSTreeNode** pRoot)//进行删除节点函数
{
    
    
    BSTreeNode* ret = *pRoot;//取得要删除节点地址
    
    if( (*pRoot)->right == NULL )//如果删除节点的右子节点等于空
    {
    
    
        *pRoot = (*pRoot)->left;//将删除节点的左子节点赋到本来指向删除节点的指针
    }
    else if( (*pRoot)->left == NULL )//如果删除节点的左子节点等于空
    {
    
    
        *pRoot = (*pRoot)->right;//将删除节点的右子节点赋到本来指向删除节点的指针
    }
    else//否则表示左右子节点都不为空
    {
    
    
        BSTreeNode* g = *pRoot;//取得要删除节点地址
        BSTreeNode* c = (*pRoot)->left;//取得要删除节点的左子节点地址
        
		//从删除节点左子节点开始找出一个键与删除节点键最接近的节点,作为删除节点的那个位置
		//因为从删除节点的左子节点开始,所以它的右子节点一直沿伸的节点的键是最接近删除节点的
		//c用于指向作为替换到删除节点位置的节点 g是c的父节点
        while( c->right != NULL )//从删除节点的左子节点往右查找,找到右节点为空的节点
        {
    
    
            g = c;//更新位置
            c = c->right;//更新下一个检测的位置
        }
        
        if( g != *pRoot )//g不等于删除节点,表示找到合适的节点
        {
    
    
			//因为c要替换到删除节点的位置,这时c节点只有左子节点(有指向或NULL)需要处理连接的,
			//因为c的右子节点确保为NULL了,经过上面的查找,再将c父节点的本来指向c节点的右子节点
			//指向c的左子节点,而且c的左子节点键肯定大于c的父节点所以是c的父节点的右子节点
			//相当替换了c节点原来的位置
            g->right = c->left;
        }
        else//否则表示删除节点的左子节点就是合适替换到删除节点位置的节点
        {
    
    
			//直接将删除节点的左子节点等于c的左子节点,这里就只有c左子节点有指向的
            g->left = c->left;
        }

        c->left = (*pRoot)->left;//将删除节点本来的左子节点部分赋给c节点左子节点
        c->right = (*pRoot)->right;//将删除节点本来的右子节部分赋给c节点的右子节点
        
        *pRoot = c;//把c节点更新到原来删除节点的指针位置
    }
    
    return ret;//返回删除节点
}

static BSTreeNode* recursive_delete(BSTreeNode** pRoot, BSKey* key, BSTree_Compare* compare)
{
    
    
    BSTreeNode* ret = NULL;
    
    if( (pRoot != NULL) && (*pRoot != NULL) )//比较节点指针地址与指向不为空
    {
    
      
		//将当前节点与key值进行比较等于0表示找到了,小于表示应该往当前节点左子节点查找,大于往右子节点查找
        int r = compare(key, (*pRoot)->key);
        
        if( r == 0 )//找到后调用删除节点函数进行删除
        {
    
    
			//注意:pRoot不是当前节点地址,是指向要删除节点的节点指针的地址(也就是树的根节点指针地址或是上一个节点的左子节点指针或右子节点指针地址)
            ret = delete_node(pRoot);//将节点指针地址作为参数进行删除操作
        }
        else if( r < 0 )
        {
    
    
			//将当前节点的左子节点指针地址调用函数继续查找
            ret = recursive_delete(&((*pRoot)->left), key, compare);
        }
        else if( r > 0 )
        {
    
    
			//将当前节点的右子节点指针地址调用函数继续查找
            ret = recursive_delete(&((*pRoot)->right), key, compare);
        }
    }
    
    return ret;
}

BSTree* BSTree_Create() // 定义创建树函数
{
    
    
    TBSTree* ret = (TBSTree*)malloc(sizeof(TBSTree));
    
    if( ret != NULL )
    {
    
    
        ret->count = 0;
        ret->root = NULL;
    }
    
    return ret;
}

void BSTree_Destroy(BSTree* tree) // 定义销毁树函数
{
    
    
    free(tree);
}

void BSTree_Clear(BSTree* tree) // 定义清空树函数
{
    
    
    TBSTree* btree = (TBSTree*)tree;
    
    if( btree != NULL )
    {
    
    
        btree->count = 0;
        btree->root = NULL;
    }
}

int BSTree_Insert(BSTree* tree, BSTreeNode* node, BSTree_Compare* compare) //定义插入节点函数
{
    
    
    TBSTree* btree = (TBSTree*)tree;//取得树
    int ret = (btree != NULL) && (node != NULL) && (compare != NULL);//判断参数不为空
    
    if( ret )
    {
    
    
        node->left = NULL;//将插入节点左子节点设空
        node->right = NULL;//将插入节点右子节点设空
        
        if( btree->root == NULL )//如果根节点等于空表示是第一个节点
        {
    
    
            btree->root = node;
        }
        else
        {
    
    
			//调用递归检测插入位置
            ret = recursive_insert(btree->root, node, compare);
        }
        
        if( ret )//如果插入成功
        {
    
    
            btree->count++;//节点数量增加
        }
    }
    
    return ret;
}

BSTreeNode* BSTree_Delete(BSTree* tree, BSKey* key, BSTree_Compare* compare)//定义删除节点函数
{
    
    
    TBSTree* btree = (TBSTree*)tree;//取得树
    BSTreeNode* ret = NULL; 
    
    if( (btree != NULL) && (key != NULL) && (compare != NULL) )//判断参数不为空
    {
    
    
        ret = recursive_delete(&btree->root, key, compare);
        
        if( ret != NULL )
        {
    
    
            btree->count--;
        }
    }
    
    return ret;
}

BSTreeNode* BSTree_Get(BSTree* tree, BSKey* key, BSTree_Compare* compare)//定义获取节点函数
{
    
    
    TBSTree* btree = (TBSTree*)tree;//取得树
    BSTreeNode* ret = NULL; 
    
    if( (btree != NULL) && (key != NULL) && (compare != NULL) )//判断参数不为空
    {
    
    
        ret = recursive_get(btree->root, key, compare);//调用递归查找 
    }
    
    return ret;//返回获取节点
}

BSTreeNode* BSTree_Root(BSTree* tree) // 定义获取根节点函数
{
    
    
    TBSTree* btree = (TBSTree*)tree;
    BSTreeNode* ret = NULL;
    
    if( btree != NULL )
    {
    
    
        ret = btree->root;
    }
    
    return ret;
}

int BSTree_Height(BSTree* tree) // 定义获取树高度函数
{
    
    
    TBSTree* btree = (TBSTree*)tree;
    int ret = 0;
    
    if( btree != NULL )
    {
    
    
        ret = recursive_height(btree->root);//调用递归计算高度函数
    }
    
    return ret;
}

int BSTree_Count(BSTree* tree) // 定义获取节点数量函数
{
    
    
    TBSTree* btree = (TBSTree*)tree;
    int ret = 0;
    
    if( btree != NULL )
    {
    
    
        ret = btree->count;
    }
    
    return ret;
}

int BSTree_Degree(BSTree* tree) // 定义获取树度数函数
{
    
    
    TBSTree* btree = (TBSTree*)tree;
    int ret = 0;
    
    if( btree != NULL )
    {
    
    
        ret = recursive_degree(btree->root);//调用递归计算度数函数
    }
    
    return ret;
}

void BSTree_Display(BSTree* tree, BSTree_Printf* pFunc, int gap, char div) //定义用统一函数处理节点函数
{
    
    
    TBSTree* btree = (TBSTree*)tree;
    
    if( btree != NULL )
    {
    
    
        recursive_display(btree->root, pFunc, 0, gap, div);
    }
}

main.c

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


struct Node
{
    
    
    BSTreeNode header;
    char v;
};

void printf_data(BSTreeNode* node)
{
    
    
    if( node != NULL )
    {
    
    
        printf("%c", ((struct Node*)node)->v);
    }
}

int compare_key(BSKey* k1, BSKey* k2)
{
    
    
    return (int)k1 - (int)k2;
}

int main(int argc, char *argv[])
{
    
    
    BSTree* tree = BSTree_Create();
    
    struct Node n1 = {
    
    {
    
    (BSKey*)1, NULL, NULL}, 'A'};
    struct Node n2 = {
    
    {
    
    (BSKey*)2, NULL, NULL}, 'B'};
    struct Node n3 = {
    
    {
    
    (BSKey*)3, NULL, NULL}, 'C'};
    struct Node n4 = {
    
    {
    
    (BSKey*)4, NULL, NULL}, 'D'};
    struct Node n5 = {
    
    {
    
    (BSKey*)5, NULL, NULL}, 'E'};
    struct Node n6 = {
    
    {
    
    (BSKey*)6, NULL, NULL}, 'F'};
    
    BSTree_Insert(tree, (BSTreeNode*)&n4, compare_key);
    BSTree_Insert(tree, (BSTreeNode*)&n1, compare_key);
    BSTree_Insert(tree, (BSTreeNode*)&n3, compare_key);
    BSTree_Insert(tree, (BSTreeNode*)&n6, compare_key);
    BSTree_Insert(tree, (BSTreeNode*)&n2, compare_key);
    BSTree_Insert(tree, (BSTreeNode*)&n5, compare_key);
    
    printf("Height: %d\n", BSTree_Height(tree));
    printf("Degree: %d\n", BSTree_Degree(tree));
    printf("Count: %d\n", BSTree_Count(tree));
    printf("Search Key 5: %c\n", ((struct Node*)BSTree_Get(tree, (BSKey*)5, compare_key))->v);
    printf("Full Tree: \n");
    
    BSTree_Display(tree, printf_data, 4, '-');
    
    BSTree_Delete(tree, (BSKey*)4, compare_key);
    
    printf("After Delete Key 4: \n");
    printf("Height: %d\n", BSTree_Height(tree));
    printf("Degree: %d\n", BSTree_Degree(tree));
    printf("Count: %d\n", BSTree_Count(tree));
    printf("Full Tree: \n");
    
    BSTree_Display(tree, printf_data, 4, '-');
    
    BSTree_Clear(tree);
    
    printf("After Clear: \n");
    printf("Height: %d\n", BSTree_Height(tree));
    printf("Degree: %d\n", BSTree_Degree(tree));
    printf("Count: %d\n", BSTree_Count(tree));
    
    BSTree_Display(tree, printf_data, 4, '-');
    
    BSTree_Destroy(tree);
    
	getchar();
	return 0;
}

分析:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_37599645/article/details/112169529