目錄:
- 代碼:
- 分析:
代碼:
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;
}
分析: