有待完善却又很创新的唐老师版二叉树

来源:互联网 发布:视频音乐制作软件 编辑:程序博客网 时间:2024/05/17 09:17

头文件

#ifndef _BTREE_H_#define _BTREE_H_/**********************转向宏定义**********************/#define BT_LEFT 0#define BT_RIGHT 1typedef unsigned long long BTPos;//用这种数的每一位代表每走一步要如何转弯typedef void BTree;//数据封装/**********************结点指针域定义**********************/typedef struct _tag_BTreeNode BTreeNode;struct _tag_BTreeNode{BTreeNode* left;BTreeNode* right;};/**********************结点指针域定义**********************/typedef void (BTree_Printf)(BTreeNode*);BTree* BTree_Create();void BTree_Destroy(BTree* tree);void BTree_Clear(BTree* tree);int BTree_Insert(BTree* tree, BTreeNode* node, BTPos pos,int count,int flag);//count代表要转几次弯,flag指明原来的子//树是作为新节点的左孩子还是右孩子BTreeNode* BTree_Delete(BTree* tree, int pos, int count);BTreeNode* BTree_Get(BTree* tree, int pos, int count);BTreeNode* BTree_Root(BTree* tree);int BTree_Height(BTree* tree);int BTree_Count(BTree* tree);int BTree_Degree(BTree* tree);void BTree_Display(BTree* tree, BTree_Printf* pFunc, int gap, char div);#endif

实现文件

#include <stdio.h>#include <malloc.h>#include "BTree.h"/**********************头节点结构体定义**********************/typedef struct _tag_BTree TBTree;struct _tag_BTree{int count;//树的节点数BTreeNode* root;//指向根节点的指针};static void recursive_display(BTreeNode* node, BTree_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(BTreeNode* 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(BTreeNode* 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(BTreeNode* 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;}BTree* BTree_Create()//和单链表类似,先申请堆空间,再合法性检测以及初始化{TBTree* ret = (TBTree*)malloc(sizeof(TBTree));if (ret != NULL){ret->count = 0;ret->root = NULL;}return ret;}void BTree_Destroy(BTree* tree)//二叉树的销毁可以直接用free{free(tree);}void BTree_Clear(BTree* tree)//要记住合法性检测{TBTree* btree = (TBTree*)tree;if (btree != NULL){btree->count = 0;btree->root = NULL;}}int BTree_Insert(BTree* tree, BTreeNode* node, BTPos pos, int count, int flag)//count代表要转几次弯{TBTree* btree = (TBTree*)tree;int ret = (btree != NULL) && (node != NULL) && ((flag == BT_LEFT) || (flag == BT_RIGHT)) ;//合法性检测int bit = 0;//后面用来判断每一位到底是1还是0,从而决定该向左还是向右if (ret){BTreeNode* parent = NULL;//需要parent和current同时工作才能正确定位//(当current移动指定次数以后有可能指向NULL)BTreeNode* current = btree->root;//parent指向上一次转过的节点,current初始为指向根节点node->left = NULL;//给要插入的节点初始化node->right = NULL;while ((count > 0) && (current != NULL)){//真正的定位bit = pos & 1;//查看最后一位是1还是0pos = pos >> 1;//取出最后一位的值以后使pos右移一位parent = current;//记录当前位置(上一次转过的节点)if (bit == BT_LEFT){//判断左拐还是右拐current = current->left;}else if (bit == BT_RIGHT){current = current->right;}count--;}/*判断以前的子树是作为新节点的左孩子还是右孩子*/if (flag == BT_LEFT){node->left = current;}else if (flag == BT_RIGHT){node->right = current;}/*判断插入的新节点是作为上一次转过的节点的左孩子还是右孩子*/if (parent != NULL){if (bit == BT_LEFT){parent->left = node;}else if (bit == BT_RIGHT){parent->right = node;}}else{//如果插入的是根节点btree->root = node;}btree->count++;//节点数更新}return ret;}BTreeNode* BTree_Delete(BTree* tree, int pos, int count){TBTree* btree = (TBTree*)tree;BTreeNode* ret = NULL;int bit = 0;if (btree != NULL){BTreeNode* parent = NULL;//需要parent和current同时工作才能正确定位//(当current移动指定次数以后有可能指向NULL)BTreeNode* current = btree->root;//parent指向上一次转过的节点,current初始为指向根节点while ((count > 0) && (current != NULL)){//真正的定位bit = pos & 1;//查看最后一位是1还是0pos = pos >> 1;//取出最后一位的值以后使pos右移一位parent = current;//记录当前位置(上一次转过的节点)if (bit == BT_LEFT){//判断左拐还是右拐current = current->left;}else if (bit == BT_RIGHT){current = current->right;}count--;}if (parent != NULL){if (bit == BT_LEFT){parent->left = NULL;//删除的是上一个节点的左孩子}else if (bit == BT_RIGHT){parent->right = NULL;}}else{btree->root = NULL;//删除的是根节点}ret = current;btree->count = btree->count - recursive_count(ret);//节点数更新}return ret;}BTreeNode* BTree_Get(BTree* tree, int pos,int count){TBTree* btree = (TBTree*)tree;BTreeNode* ret = NULL;int bit = 0;if (btree != NULL){BTreeNode* current = btree->root;//Get的时候只需要current就可以定位while ((count > 0) && (current != NULL)){//真正的定位bit = pos & 1;//查看最后一位是1还是0pos = pos >> 1;//取出最后一位的值以后使pos右移一位if (bit == BT_LEFT){//判断左拐还是右拐current = current->left;}else if (bit == BT_RIGHT){current = current->right;}count--;}ret = current;}return ret;}BTreeNode* BTree_Root(BTree* tree){TBTree* btree = (TBTree*)tree;BTreeNode* ret = NULL;if (btree != NULL){ret = btree->root;}return ret;}int BTree_Height(BTree* tree){TBTree* btree = (TBTree*)tree;int ret = -1;if (btree != NULL){ret = recursive_height(btree->root);}return ret;}int BTree_Count(BTree* tree){TBTree* btree = (TBTree*)tree;int ret = -1;if (btree != NULL){ret = btree->count;}return ret;}int BTree_Degree(BTree* tree){TBTree* btree = (TBTree*)tree;int ret = -1;if (btree != NULL){ret = recursive_degree(btree->root);}return ret;}//传入的是tree,实际上操作的是node,且从root开始void BTree_Display(BTree* tree, BTree_Printf* pFunc, int gap, char div){TBTree* btree = (TBTree*)tree;//先类型转换if (btree != NULL){recursive_display(btree->root,pFunc,0,gap,div);}}

测试程序

#include <stdio.h>#include "BTree.h"struct Node//要插入的实际数据元素结构体{BTreeNode header;char v;//实际的数据};void printf_data(BTreeNode* node){if (node != NULL){printf("%c",((struct Node*)node)->v);}}int main(){BTree* tree = BTree_Create();struct Node n1 = { { NULL, NULL }, 'A' };struct Node n2 = { { NULL, NULL }, 'B' };struct Node n3 = { { NULL, NULL }, 'C' };struct Node n4 = { { NULL, NULL }, 'D' };struct Node n5 = { { NULL, NULL }, 'E' };struct Node n6 = { { NULL, NULL }, 'F' };BTree_Insert(tree, (BTreeNode*)&n1, 0, 0, BT_LEFT);BTree_Insert(tree, (BTreeNode*)&n2, 0x00, 1, 0);BTree_Insert(tree, (BTreeNode*)&n3, 0x01, 1, 0);BTree_Insert(tree, (BTreeNode*)&n4, 0x00, 2, 0);BTree_Insert(tree, (BTreeNode*)&n5, 0x02, 2, 0);BTree_Insert(tree, (BTreeNode*)&n6, 0x02, 3, 0);printf("Height: %d\n", BTree_Height(tree));printf("Degree: %d\n", BTree_Degree(tree));printf("Count: %d\n", BTree_Count(tree));printf("Position At (0x02, 2): %c\n", ((struct Node*)BTree_Get(tree, 0x02, 2))->v);printf("Full Tree: \n");BTree_Display(tree, printf_data, 4, '-');BTree_Delete(tree, 0x00, 1);printf("After Delete B: \n");printf("Height: %d\n", BTree_Height(tree));printf("Degree: %d\n", BTree_Degree(tree));printf("Count: %d\n", BTree_Count(tree));printf("Full Tree: \n");BTree_Display(tree, printf_data, 4, '-');BTree_Clear(tree);printf("After Clear: \n");printf("Height: %d\n", BTree_Height(tree));printf("Degree: %d\n", BTree_Degree(tree));printf("Count: %d\n", BTree_Count(tree));BTree_Display(tree, printf_data, 4, '-');BTree_Destroy(tree);system("PAUSE");return 0;}


0 0