二插排序树

二分查找只适用于静态查找,不适合改变查找表。当然他们的时间复杂度都是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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值