值得一说的是删除操作,删除操作我们分为三种情况:

1.要删的节点有两个孩子:

  找到左子树中的最大值或者右子树中的最小值所对应的节点,记为node,并把node的值赋给要删除的节点del,然后删除node

实际上真正删除的是node,del只是发生了一次值的替换。

为了方便理解和操作,我们把两个孩子的情况放在最前面,这样经过以上处理后,该节点就会变成情况2或者情况3 ,接下爱这行这两种情况的代码。

2.要删的节点有一个孩子

r判断要删除的节点del是其父亲father的左孩子还是右孩子,以是father的左孩子为例,del是father的左孩子,接下来判断del是否有左孩子,

如果有,则father的左孩子变成del的左孩子,如果没有,则father的左孩子变成del的右孩子。

3.要删的节点没有孩子

即为当情况2 del的左孩子右孩子为空的时候

#include<stdio.h>
#include<stdlib.h>
typedef struct Tree
{
int data;
Tree*right;
Tree*left;
}BinaryTree;
void insert(BinaryTree **p,int e)
{
BinaryTree *temp=(BinaryTree*)malloc(sizeof(BinaryTree));
temp->data=e;
temp->left=NULL;
temp->right=NULL; if(*p==NULL)
{
*p=temp;
return ;
}
BinaryTree*root=*p;
while(1)
{
if(e<root->data)
{
if(root->left)
{
root=root->left;
}
else
{
root->left=temp;
break;//完成插入操作了
} }
else if(e>root->data)
{
if(root->right)
{
root=root->right; }
else
{
root->right=temp;
break;
}
}
}
}
void FindNode(BinaryTree* p,BinaryTree **del,BinaryTree**father, int e)//我们在删除操作中不仅需要知道要删除哪个节点,还要知道要删除节点的父亲
{                                          //return无法返回两个值,要实现返回两个值,我们在这里采用二级指针
while(1) //实际上也可以通过结构体封装来完成同时返回两个值
{
if(e<p->data)
{
*father=p;//每次都记录一下父亲
p=p->left;
}
else if(e>p->data)
{
*father=p;
p=p->right;
}
else if(e==p->data)
{
*del=p;return ;
}
}
}
void deleteNode(BinaryTree **p,int e)//
{
if(*p==NULL) return ;
BinaryTree *root=*p;
BinaryTree *del=NULL;
BinaryTree *father=NULL;
BinaryTree *pmark=NULL;
FindNode(root,&del,&father,e);
if(del->left&&del->right)
{
pmark=del;//标记要删除的点
father=del;
del=del->left;
while(del->right)
{
father=del;
del=del->right;
}
pmark->data=del->data;
}
//接下来分析有一个或者没有孩子的情况
//被删节点 是根
if(father==NULL)//??
{
*p=del->left?del->left:del->right;
free(del);
return ;
}
else
{//不用在写判断条件了,走到这说明就是一个或者没有孩子,只需要判断是哪边的孩子就可
if(del==father->left)
father->left=del->left?del->left:del->right;
else if(del==father->right)
father->right=del->left?del->left:del->right;
free(del); }
}
void inorder(BinaryTree *p)
{
if(p==NULL) return ;
//递归要有结束条件
inorder(p->left);
printf(" %d ",p->data);
inorder(p->right);
}
void preorder(BinaryTree *p)
{
if(p==NULL) return ;
//递归要有结束条件 printf(" %d ",p->data);
preorder(p->left);
preorder(p->right);
}
int main()
{
int m;
BinaryTree *p=NULL;
int a[10];
int i;
scanf("%d",&m);
for(i=0;i<m;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<m;i++)
{
insert(&p,a[i]);
}
preorder(p);
printf("\n");
inorder(p);
deleteNode(&p,9);
preorder(p);
printf("\n");
inorder(p);
return 0;
}

  

BST(二叉排序树)的插入与删除的更多相关文章

  1. 二叉搜索树(BST)的插入和删除递归实现

    思路 二叉搜索树的插入 TreeNode InsertRec(rootNode, key) = if rootNode == NULL, return new Node(key) if key > ...

  2. 数据结构学习-BST二叉查找树 : 插入、删除、中序遍历、前序遍历、后序遍历、广度遍历、绘图

    二叉查找树(Binary Search Tree) 是一种树形的存储数据的结构 如图所示,它具有的特点是: 1.具有一个根节点 2.每个节点可能有0.1.2个分支 3.对于某个节点,他的左分支小于自身 ...

  3. Java实现二叉排序树的插入、查找、删除

    import java.util.Random; /** * 二叉排序树(又称二叉查找树) * (1)能够是一颗空树 * (2)若左子树不空,则左子树上全部的结点的值均小于她的根节点的值 * (3)若 ...

  4. 算法与数据结构(十) 二叉排序树的查找、插入与删除(Swift版)

    在上一篇博客中,我们主要介绍了四种查找的方法,包括顺序查找.折半查找.插入查找以及Fibonacci查找.上面这几种查找方式都是基于线性表的查找方式,今天博客中我们来介绍一下基于二叉树结构的查找,也就 ...

  5. 详细教你实现BST(二叉排序树)

    查找基本分类如下: 线性表的查找 顺序查找 折半查找 分块查找 树表的查找 二叉排序树 平衡二叉树 B树 B+树 散列表的查找 今天介绍二叉排序树. 二叉排序树 ( Binary Sort Tree ...

  6. 二叉查找树(查找、插入、删除)——C语言

    二叉查找树 二叉查找树(BST:Binary Search Tree)是一种特殊的二叉树,它改善了二叉树节点查找的效率.二叉查找树有以下性质: (1)若左子树不空,则左子树上所有节点的值均小于它的根节 ...

  7. 二叉查找树的查找、插入和删除 - Java实现

    http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 作者: yangecnu(yangecnu's Blog on ...

  8. 【算法】【python实现】二叉搜索树插入、删除、查找

    二叉搜索树 定义:如果一颗二叉树的每个节点对应一个关键码值,且关键码值的组织是有顺序的,例如左子节点值小于父节点值,父节点值小于右子节点值,则这棵二叉树是一棵二叉搜索树. 类(TreeNode):定义 ...

  9. AVL树的插入和删除

    一.AVL 树 在计算机科学中,AVL树是最早被发明的自平衡二叉查找树.在AVL树中,任一节点对应的两棵子树的最大高度差为 1,因此它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下的时间复杂度 ...

  10. 我的MYSQL学习心得(八) 插入 更新 删除

    我的MYSQL学习心得(八) 插入 更新 删除 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得( ...

随机推荐

  1. mysql explicit_defaults_for_timestamp 变量的作用

    mysql 中有这样的一个默认行为,如果一行数据中某些列被更新了,如果这一行中有timestamp类型的列,那么么这个timestamp列的数据 也会被自动更新到 更新操作所发生的那个时间点:这个操作 ...

  2. MySQL中的基本SQL语句

    标准SQL包含了4种基本的语句类别: DDL语句,数据定义语句,主要用来定义数据库,表名,字段,例如create,drop,alter. DML语句,数据操作语句,用来对数据记录的增删改查,还用来保证 ...

  3. 20145216史婧瑶 《网络对抗》 MSF基础应用

    20145216史婧瑶 <网络对抗> MSF基础应用 实验回答问题 用自己的话解释什么是exploit,payload,encode. exploit:渗透攻击模块,测试者利用它来攻击一个 ...

  4. linux内核分析 第五周

    一.实验相关 1.下载老师最新的menu文件,并在其中添加上周所编写的代码,并运行 下载 添加 运行 2.gdb调试跟踪 gdb设置跟踪文件(先进入linux-3.18.6所在的文件) gdb设置断点 ...

  5. 在awk中通过system调用sql语句来说明引号的使用

    一个实际应用例子: 在awk中,通过system调用连接数据库并作select操作,select语句中where条件来自于一个文件(file)的第一个域($1). $ cat file ... ... ...

  6. Where is HttpContent.ReadAsAsync?

    It looks like it is an extension method (in System.Net.Http.Formatting): HttpContentExtensions Class ...

  7. Codeforces Round #530 (Div. 1)

    A - Sum in the tree 就是贪心选尽量让上面的点权尽量大,那么对于偶数层的点,其到根节点的和即为所有儿子中的最大值. #include<bits/stdc++.h> usi ...

  8. sql 之优化小技巧

    SET NOCOUNT ON:不返回计数,如果存储过程中包含一些并不返回实际数据的语句,网络通信流量便会大量减少,可以显著提高应用程序性能:

  9. [Shiro] - 基于URL配置动态权限

    基于shiro进阶 更改了数据库表 之前的PageController是通过@RequiresPermissions和@RequiresRoles进行是否有权限/是否有角色的判定调用@RequestM ...

  10. bzoj 3289: Mato的文件管理 莫队+树状数组

    3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Mato同学 ...