1238 字
6 分钟
二叉树排序树插入、创建、删除和查找
二叉树排序树插入、创建、删除和查找
二叉排序树的概念
二叉排序树又称二叉查找树,它或者是一棵空树,或者是具有下列性质的二叉树
- 若它的左子树不为空,则左子树上所有结点的值均小于根结点的值
- 若它的右子树不为空,则右子树上所有结点的值均小于根节点的值
- 它的左右子树也同样是二叉排序树
二叉排序树的插入
二叉排序树的插入就是按照二叉树的定义将新结点放到相应位置
实现代码:
// 二叉排序树插入void search_createBinarySortTree_insert(TreeNode* r, int value){ int v = 0; while(1) { v = r->value;
if(value < v) { // 当value小于当前结点的值时
if(r->lchild == NULL) { // 若当前结点没有左子树,将value赋给当前节点的左子树
// 创建一个二叉树结点并添加到当前结点的相应位置 addTreeNodeChild(r, createTreeNode(value), 'l'); return; } else { // 当当前节点有左子树,去左子树找 r = r->lchild; } } else { // 当value大于当前节点的值时
if(r->rchild == NULL) { // 若当前节点没有右子树,将value赋给当前节点的左子树
addTreeNodeChild(r, createTreeNode(value), 'r'); return; } else { // 当当前节点有右子树时,去右子树找 r = r->rchild; } } }}通过数组创建二叉排序树
按顺序遍历数组,对每个元素进行二叉排序树插入操作
实现代码:
// 生成二叉排序树TreeNode* search_createBinarySortTree(int* arr, int len){ // 因为一开始是空树,所有先创建一个根节点 TreeNode* root = createTreeNode(arr[0]);
// 对剩下的元素进行插入 for(int i = 1; i < len; i ++) { search_createBinarySortTree_insert(root, arr[i]); } return root;}二叉排序树的删除
二叉排序树的删除有三种情况,叶子结点、有两棵子树的结点、有一棵子树的结点
-
叶子结点
直接删除即可
-
有两棵子树的结点
有几种方法可以实现,如①用左子树的最右结点替代当前结点、②用右子树的最左结点替代当前结点。
-
有一棵子树的结点
用子树替代当前结点即可
实现代码:
// 二叉排序树删除节点/*target:要删除的结点parent:双亲结点targetIs:要删除的结点是双亲的左孩子还是右孩子,'r'表示右孩子;'l'表示左孩子。为了看起来方便没用0,1表示但发现写起来还是用0,1舒服*/void search_createBinarySortTree_delete(TreeNode* target, TreeNode* parent, char targetIs){ if(target->lchild == NULL && target->rchild == NULL) { // 是叶子结点,直接删除 deleteTreeNodeChild(parent, targetIs); } else if(target->lchild && target->rchild) { TreeNode* tmp; TreeNode* tmp_past = NULL; // 有两个孩子结点
/* 用右子树的最左边结点替代当前结点 */ tmp = target->rchild; while(tmp->lchild) { tmp_past = tmp; tmp = tmp->lchild; }
// 将要替换的结点从树中删除 deleteTreeNodeChild(tmp_past? tmp_past:target, tmp_past? 'l':'r');
// 替换要删除的节点 // 替换子树 tmp->rchild = target->rchild; tmp->lchild = target->lchild; // 替换双亲 addTreeNodeChild(parent, tmp, targetIs); } else { // 当前结点只有一个子树 char haveChild; if(target->lchild) haveChild = 'l'; else haveChild = 'r';
// 让子树替代当前节点的位置 addTreeNodeChild(parent, deleteTreeNodeChild(target, haveChild), targetIs); }
// 将要删除节点的子树置空 deleteTreeNodeChild(target, 'r'); deleteTreeNodeChild(target, 'l');}二叉树查找
查找相关的结点,若找到,删除并将其返回,否则返回空
实现代码:
// 二叉树查找// 返回删除的节点TreeNode* search_binarySortTreeSearch(TreeNode* root, int value){ // 用来存放要删除结点的双亲 TreeNode* r_past = root; //RL:用来表示要删除的结点相对于双亲是左子树还是右子树 char RL; while(1) { // 未找到,返回空 if(root == NULL) return NULL;
// 找到,退出循环 if(root->value == value) { break; } else if(value < root->value) { r_past = root; root = root->lchild; RL = 'l'; } else { r_past = root; root = root->rchild; RL = 'r'; } }
// 删除相应结点,并返回 search_createBinarySortTree_delete(root, r_past, RL); return root;}代码测试
测试代码:
/*测试数据:-1,5,2,7,1,4,6,8,3因为忘记写根节点处理了,所有加个-1结点*/
/*tree:二叉排序树value:要查找的树*/void print_result(TreeNode* tree, int value){ tree = search_binarySortTreeSearch(tree, value); if(tree) { printf("找到值为 %d 的元素\n", tree->value); } else { printf("没找到值为 %d 的元素\n", value); } // 通过先序遍历和中序遍历确认树结构 printf("\n先序遍历:"); preOrder(tree, "%d "); printf("\n中序遍历:"); inOrder(tree, "%d ");}样例结构:

测试样例:
-
删除叶子结点
删除 8 结点
结果:

-
有两个子树的结点
删除 5 结点
结果:

-
有一个子树的结点
删除 4 结点
结果:

-
无效结点
删除 0 结点
结果:

原文链接:CSDN
二叉树排序树插入、创建、删除和查找
https://blog.homura.work/posts/csdn/109540685/