目录:

  • 代码:
  • 分析:

代码:

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参数返回负数,大于返回正数,等于返回0if( 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;
}

分析:











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

  1. 二叉查找树(binary search tree)详解

    二叉查找树(Binary Search Tree),也称二叉排序树(binary sorted tree),是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有结点的值均小于 ...

  2. 问题六十四:怎么用C++实现二叉查找树(binary search tree)及其相关操作

    64.0 概述 什么是二叉查找树(binary search tree)? 二叉查找树(binary search tree)又叫二叉排序树(binary ordered tree). 对于任意二叉查 ...

  3. 学习数据结构 二叉查找树(binary search tree)

    2019独角兽企业重金招聘Python工程师标准>>> 为学习 LLVM 的 ImmutableSet,其底层的实现选择为 AVL 树(平衡二叉搜索树),我不很熟悉该树,虽然大致知道 ...

  4. 【LeetCode-面试算法经典-Java实现】【109-Convert Sorted List to Binary Search Tree(排序链表转换成二叉排序树)】...

    [109-Convert Sorted List to Binary Search Tree(排序链表转换成二叉排序树)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 ...

  5. binary search tree python_二叉查找树(binary search tree)——python实现

    二叉查找树(binary search tree) 顾名思义二叉查找树中每个节点至多有两个子节点,并且还对存储于每个节点中的关键字值有个小小的要求, 即只要这个节点有左节点或右节点,那么其关键字值总的 ...

  6. 数据结构与算法(C++)– 二叉查找树(Binary Search Tree )

    数据结构与算法(C++)– 二叉查找树(Binary Search Tree ) 1.二叉查找树(BST) 定义: 假设二叉树的节点都是不同的数,对于树点的任一节点,它的左子树都小于它,它的右子树都大 ...

  7. BST(Binary Search Tree 二叉查找树模版)

    /****************************************** 数据结构: BST(Binary Search Tree),二叉查找树;性质: 若结点的左子树不空,则左子树上所 ...

  8. 1043 Is It a Binary Search Tree(二叉查找树BST)

    1043 Is It a Binary Search Tree 0.题目 A Binary Search Tree (BST) is recursively defined as a binary t ...

  9. Recover Binary Search Tree,恢复二叉排序树

    问题描述:题意就是二叉树中有两个节点交换了,恢复结构. Two elements of a binary search tree (BST) are swapped by mistake. Recov ...

最新文章

  1. 使用WebRTC搭建前端视频聊天室——数据通道篇
  2. Android适配难题全面总结
  3. FilterDispatcher is deprecated! Please use
  4. 启动Activity的两种方式startActivity和startActivityForResult(一)
  5. 以太坊源码学习 -- EVM
  6. OpenFOAM中slip和noslip介绍(滑移条件无滑移条件)【翻译】
  7. 中国深圳,600架无人机的盛典!
  8. Android—逐帧、补间、属性动画
  9. “西邮漫记”--自由照耀中国
  10. 对自定义UITableViewCell的理解
  11. day1-4js算术运算符及类型转化
  12. todo Java 并发编程
  13. python迭代器和生成器_python迭代器和生成器
  14. C2000系列DSP生成hex/bin文件并使用串口下载程序的方法
  15. iOS不完美越狱手机doubleH3lix无法打开解决方法
  16. 做中学之五笔输入法实践教程
  17. 计算机桌面美化软件,桌面美化软件哪个好_桌面美化软件排行榜【最新】-太平洋电脑网...
  18. C# 生成订单编号和取餐码
  19. java7G怎么表示_Java研发方向如何准备BAT技术面试答案(上)
  20. 如何用html自动关机电脑,如何设置电脑完东西自动关机

热门文章

  1. 天涯明月刀7月4号服务器维护,7月8日服务器例行维护公告
  2. React - antd4 中在form中为Switch赋值无效
  3. Angularjs基础(三)
  4. 基于webpack搭建的vue element-ui框架
  5. Sum of Even Numbers After Queries
  6. [No0000187]可能是把Java内存区域讲的最清楚的一篇文章
  7. 洛谷P1937 [USACO10MAR]仓配置Barn Allocation
  8. Owner Useful links
  9. android junit 测试程序
  10. JavaScript 参考教程(二)——转载