数据结构设计
#define BST_NODE_CHILD 0
#define BST_NODE_PARENT 1
//bst的节点
typedef struct bst_node
{
//关键字
int key;
//左孩子
bst_node* left;
//右孩子
bst_node* right;
}bst_node;
//bst树
typedef struct bst
{
//树的节点
struct bst_node* root;
//记录树的节点数目
int size;
}bst;
接口设计
//创建一个空的二叉搜索树
bst* bst_create();
//创建一个bst的节点
bst_node* bst_create_node(int key);
//查找节点(type为选择查找目标的父节点还是本身);
bst_node* bst_search_node(bst_node* node, int type, int key);
//搜索子树中最大节点或其父节点
bst_node* bst_find_max_node(bst_node* node, int type);
//插入节点
bst* bst_insert_node(bst* bst, int key);
//删除节点
void bst_delete_node(bst* bst, int key);
//中序遍历
void bst_inorder_traversal(bst_node* node);
测试
int main()
{
bst* bst = bst_create();
int arr[] = { 21,3,5,26,29,50,18,53,8,67,1,78,6 };
int length = sizeof(arr) / sizeof(int);
for (int i = 0; i < length; i++)
{
bst_insert_node(bst, arr[i]);
printf("size:%d ", bst->size);
printf("中序遍历:");
bst_inorder_traversal(bst->root);
printf("\n");
}//end_for
for (int i = length - 1; i >= 0; i--)
{
bst_delete_node(bst, arr[i]);
printf("size:%d ", bst->size);
printf("中序遍历:");
bst_inorder_traversal(bst->root);
printf("\n");
}//end_for
free(bst);
return 0;
}
接口实现
//创建一个空的二叉搜索树
bst* bst_create()
{
bst* bst = (struct bst*)malloc(sizeof(struct bst));
if (bst == NULL)
return NULL;
bst->root = NULL;
bst->size = 0;
return bst;
}
//创建一个bst的节点
bst_node* bst_create_node(int key)
{
bst_node* node = (struct bst_node*)malloc(sizeof(struct bst_node));
if (node == NULL)
return NULL;
node->left = NULL;
node->right = NULL;
node->key = key;
return node;
}
//查找节点(type为选择查找目标的父节点还是本身)
bst_node* bst_search_node(bst_node* node, int type, int key)
{
bst_node* cur = node;
bst_node* parent = NULL;
if (cur == NULL)
return NULL;
while (cur != NULL)
{
if (key < cur->key)
{
parent = cur;
cur = cur->left;
}
else if (key == cur->key)
{
break;
}
else
{
parent = cur;
cur = cur->right;
}//end_if
}//end_while
if (type == BST_NODE_CHILD)
return cur;
return parent;
}
//搜索子树中最大节点或其父节点
bst_node* bst_find_max_node(bst_node* node, int type)
{
bst_node* cur = node;
bst_node* parent = NULL;
if (cur == NULL)
return NULL;
while (cur->right != NULL)
{
parent = cur;
cur = cur->right;
}//end_while
if (type == BST_NODE_CHILD)
return cur;
return parent;
}
//插入节点
bst* bst_insert_node(bst* bst, int key)
{
bst_node* cur = bst->root;
bst_node* parent = NULL;
//如果是空树,则新建节点作为根节点
if (cur == NULL)
bst->root = bst_create_node(key);
else
{
//不是空树则先找到带插入节点的父节点
parent = bst_search_node(bst->root, BST_NODE_PARENT, key);
if (parent == NULL)
return NULL;
if (key < parent->key)
parent->left = bst_create_node(key);
else if (key == parent->key)
return NULL;
else if (key > parent->key)
parent->right = bst_create_node(key);
}//end_if
bst->size++;
return bst;
}
//删除节点
void bst_delete_node(bst* bst, int key)
{
//找到待删除节点的父节点
bst_node* parent = bst_search_node(bst->root, BST_NODE_PARENT, key);
//cur为待删除节点,tmp为删除节点的接管者,max为cur的子树接管者
bst_node* cur, * tmp, * max;
cur = bst_search_node(bst->root, BST_NODE_CHILD, key);
if (parent == NULL && cur == NULL)
{
//如果是只有根节点的树,则直接删除
tmp = bst->root;
bst->root = NULL;
}
if (parent == NULL)
return;
else if (cur->left == NULL && cur->right == NULL)
{
//该节点是终端节点,则直接删除即可
if (cur->key < parent->key)
{
tmp = parent->left;
parent->left = NULL;
}
else
{
tmp = parent->right;
parent->right = NULL;
}//end_if
}
else if (cur->left==NULL)
{
tmp = cur->right;
cur->key = cur->right->key;
cur->left = cur->right->left;
cur->right = cur->right->right;
}
else if (cur->right == NULL)
{
//该节点右子树为空
tmp = cur->left;
cur->key = cur->left->key;
cur->left = cur->left->left;
cur->right = cur->left->right;
}
else
{
//左右子树都不为空
max = bst_find_max_node(cur->left, BST_NODE_PARENT);
if (max == NULL)
{
//说明cur的left没有parent,最大值就是其本身
tmp = cur->left;
cur->key = cur->left->key;
//最大值为本身,没有右子树
cur->left = cur->left->left;
}
else
{
tmp = max->right;
cur->right->key = max->right->key;
max->right = max->right->left;
}//end_if
}//end_if
free(tmp);
bst->size--;
return;
}
//中序遍历
void bst_inorder_traversal(bst_node* node)
{
if (node != NULL)
{
bst_inorder_traversal(node->left);
printf("%d\t", node->key);
bst_inorder_traversal(node->right);
}
}