二叉搜索树的建立 添加结点 删除结点
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); }