二分查找只适用于静态查找,不适合改变查找表。当然他们的时间复杂度都是logn
头文件
#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* key1, BSKey* key2);
BSTree* BSTree_Create();
void BSTree_Destroy(BSTree* tree);
void BSTree_Clear(BSTree* tree);
int BSTree_Insert(BSTree* tree, BSTreeNode* node, BSTree_Compare* pFunc);//count代表要转几次弯,flag指明原来的子 //树是作为新节点的左孩子还是右孩子
BSTreeNode* BSTree_Delete(BSTree* tree, BSKey* key,BSTree_Compare* pFunc);
BSTreeNode* BSTree_Get(BSTree* tree, BSKey* key, BSTree_Compare* pFunc);
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
实现文件
#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){
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) // O(n)递归求节点数
{
int ret = 0;
if (root != NULL)
{
ret = recursive_count(root->left) + 1 + recursive_count(root->right);//左子树 + 右子树 +根节点
}
return ret;
}
static int recursive_height(BSTreeNode* node)
{
int ret = 0;
if (node != NULL){
int L_Height = recursive_height(node->left);
int R_Height = recursive_height(node->right);
ret = ((L_Height > R_Height) ? L_Height : R_Height) + 1;//不要忘了加上根节点
}
return ret;
}
static int recursive_degree(BSTreeNode* node)
{
int ret = 0;
if (node != NULL){
if (node->left != NULL){
ret++;
}
if (node->right != NULL){
ret++;
}
if (ret == 1){
int ld = recursive_degree(node->left);
int rd = recursive_degree(node->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;
ret = (root != NULL) && (node != NULL) && (compare != NULL);
if (ret){
int r = compare(node->key,root->key);
if (0 == r){//如果已经有了这个节点,返回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 (0 == r){//关键字和当前节点的匹配则将当前节点返回
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** root){
BSTreeNode* ret = *root;//记录要删除的节点并返回
if ((*root)->right == NULL){//如果右孩子为空则将左孩子提上来
(*root) = (*root)->left;
}
else if ((*root)->left == NULL){//如果左孩子为空则将右孩子提上来
(*root) = (*root)->right;
}
else{//有两个不为空的孩子
BSTreeNode* g = *root;//因为root是二级指针
BSTreeNode* c = (*root)->left;//记录要删除节点的左孩子
while (c->right != NULL){//一般情况是先查看要删除节点的左孩子,再递归的查看其左孩子的右子树,直到遇到叶节点
g = c;
c = c->right;//不断查找下一个右孩子
}
if (g != *root){//如果经过了一个及以上的右孩子且最先经过一个左孩子,却又可能最后一个右孩子有一个左孩子,则最 //后要将他的左孩子变为上一个节点的右孩子
g->right = c->left;
}
else{//如果一次右孩子都没有经历过,即没有经过while循环,则直接将当前节点的左孩子提上来使得树连贯起来不间断
g->left = c->left;
}
c->left = (*root)->left;//将c指向的节点直接替代要删除的节点,三个步骤都不能缺少
c->right = (*root)->right;
*root = c;
}
return ret;
}
static BSTreeNode* recursive_delete(BSTreeNode** root, BSKey* key, BSTree_Compare* compare)
{
BSTreeNode* ret = NULL;
if ((root != NULL) && (*root != NULL)){
int r = compare(key,(*root)->key);
if (0 == r){
ret = delete_node(root);
}
else if(r < 0){
ret = recursive_delete(&((*root)->left),key,compare);
}
else if (r > 0){
ret = recursive_delete(&((*root)->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
{
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* pFunc)
{
TBSTree* btree = (BSTree*)tree;
int ret = (btree != NULL) && (node != NULL) && (pFunc != NULL);//合法性判断
if (ret){
node->left = NULL;//记得使用之前给所有指针变量赋值
node->right = NULL;
if (btree->root == NULL){//如果树原来为空则插入的是根节点
btree->root = node;
}
else{//否则递归的找到叶节点再插入
ret = recursive_insert(btree->root,node,pFunc);
}
if (ret){//有可能树里面已经有了要插入的节点,此时将不会插入新节点,所以节点数不一定增加
btree->count++;
}
}
return ret;
}
BSTreeNode* BSTree_Delete(BSTree* tree, BSKey* key, BSTree_Compare* pFunc)
{
TBSTree* btree = (TBSTree*)tree;
BSTreeNode* ret = NULL;
if ((btree != NULL) && (key != NULL) && (pFunc != NULL)){//合法性判断
ret = recursive_delete(&btree->root,key,pFunc);
if (ret != NULL){//返回一个非空的值则表示删除成功,才可以将节点数减少
btree->count--;
}
}
return ret;
}
BSTreeNode* BSTree_Get(BSTree* tree, BSKey* key, BSTree_Compare* pFunc)
{
TBSTree* btree = (BSTree*)tree;
BSTreeNode* ret = NULL;
if ((btree != NULL) && (key != NULL) && (pFunc != NULL)){//合法性判断
ret = recursive_get(btree->root,key,pFunc);
}
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 = -1;
if (btree != NULL){
ret = recursive_height(btree->root);
}
return ret;
}
int BSTree_Count(BSTree* tree)
{
TBSTree* btree = (TBSTree*)tree;
int ret = -1;
if (btree != NULL){
ret = btree->count;
}
return ret;
}
int BSTree_Degree(BSTree* tree)
{
TBSTree* btree = (TBSTree*)tree;
int ret = -1;
if (btree != NULL){
ret = recursive_degree(btree->root);
}
return ret;
}
//传入的是tree,实际上操作的是node,且从root开始
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);
}
}
测试文件
#include <stdio.h>
#include <stdlib.h>
#include "BSTree.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
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);
system("PAUSE");
return 0;
}