BST_t* create()
{
return calloc(1, sizeof(BST_t));
}
void insert(BST_t* tree, char key)
{
TreeNode_t* prev = NULL;
TreeNode_t* curr = tree->root;
//查找插入的位置 那个位置肯定是空结点了 其目的不是找到curr而是确定prev
//因为curr已经是空结点了,无法被赋值,而prev则存在于树的末端
while (curr != NULL)
{
prev = curr;
if (key < curr->key)
curr = curr->left;
else if (key > curr->key)
curr = curr->right;
else
return;
}
//小驼峰命名法 好习惯 创建新结点
TreeNode_t* newNode = calloc(1,sizeof(TreeNode_t));//用calloc好可以直接初始化为NULL,
//因为tree的左右子树需要判断是否为NULL
if (newNode == NULL)
{
printf("创建结点失败!");
return;
}
newNode->key = key;//给新结点的key成员赋值
//插入结点 第一次要判断根结点指向 不然一直指向NULL 改变的是curr的指向而不会是root
//后面添加新结点也是一样的情况,必须拿prev的左右来指向新结点 不能用curr
if (tree->root == NULL)
tree->root = newNode;
else if (key < prev->key)
prev->left = newNode;
else
prev->right = newNode;
return;
}
void rm(BST_t* tree, char key)
{
TreeNode_t* prev = NULL;
TreeNode_t* curr = tree->root;
//寻找要删除的结点
while (curr != NULL)
{
if (key < curr->key)
{
prev = curr;
curr = curr->left;
}
else if (key > curr->key)
{
prev = curr;
curr = curr->right;
}
else
break;
}
//没找到的情况
if (curr == NULL)
{
return false;
}
//第一种情况:待删除结点度为2。移花接木
if (curr->left != NULL && curr->right != NULL)
{
//度为2的情况 我们准备将右子树中最小的值替换上来 再把本体删掉
TreeNode_t* parent = curr;
TreeNode_t* minOfRight = curr->right;
while (minOfRight->right != NULL)
{
parent = minOfRight;
minOfRight = minOfRight->left;
}
//替换 先把右边最小的那个值拷贝过来,再想办法把右边最小值干掉,也就是转嫁成度为0或1的情况
curr->key = minOfRight->key;
prev = parent;
curr = minOfRight;
}
// 处理度为0和度为1的情况 child就是要续上的那个结点
//因为只有度为0和度为1两种情况。左子树存在便续左子树,右子树存在
//便续右子树(即使它们会是NULL)
TreeNode_t* child = curr->left != NULL ? curr->left : curr->right;
if (prev == NULL)//删除整个树的根结点的情况
tree->root = child;
//变成child 再干掉原来的child
else if(curr->key < prev->key)
prev->left = child;
else
prev->right = child;
free(curr);
}