DS-二叉排序树的插入、查找和删除
2019-12-02
Data Structure 之 二叉排序树
二叉排序树是给定一个节点后,接下来插入的数如果比它大就会放到它的右孩子那边,比它小就会放到它的左孩子那边。
所以对于相同的一个节点下的左右孩子,左孩子 < 根节点 < 右孩子。
节点
由简单的左孩子和右孩子指针加上数据就可以构成一个节点。
//BST节点
struct BSTNode{
int data;
BSTNode *RightChild;
BSTNode *LeftChild;
BSTNode(){
RightChild = NULL;
LeftChild = NULL;
}
};
二叉排序树的类
多的功能不会只需要有一个root的根节点。
插入
插入操作是一个基本,写好后在建树的时候直接调用插入函数就可以将所有元素插入到树里面。
在这里有一个递归的思想但是没有用到函数递归调用的方法。
对于要插入的数,从根节点开始比较,如果比当前节点大就往当前节点右孩子方向走,否则相反。
void Insert(int num){ BSTNode *temp = root;//记录头结点位置 while(1){//模拟递归的遍历
if(num>temp->data){
if(temp->RightChild!=NULL){
temp=temp->RightChild;
}
else{//如果当前节点右孩子为NULL,则新建一个空间储存插入的数据
temp->RightChild = new BSTNode();
temp->RightChild->data = num;
break;
}
}
else{
if(temp->LeftChild!=NULL){
temp=temp->LeftChild;
}
else{
temp->LeftChild = new BSTNode();
temp->LeftChild->data = num;
break;
}
}
}
}
建树
写好了插入函数后建树就简单了,用数组num和数组大小当参数传递给creatBST函数。
将root节点的data赋值为num【0】,也就是数组第一个元素。
其他的元素用插入函数完成插入即可。
void creatBST(int num[],int n){ root = new BSTNode();
root->data = num[0]; for(int i=1;i<n;i++)
this->Insert(num[i]);
}
查找
查找的思路其实很简单,就是遍历一遍,这里下标采用中序遍历的计数。
int Find(int num){ BSTNode *temp = root; int sum=0; while(1){
if(temp->RightChild==NULL&&temp->LeftChild==NULL&&num!=temp->data){
return -1;
}
sum++;
if(num==temp->data){
return sum;
}
else if(num>temp->data&&temp->RightChild!=NULL){
temp=temp->RightChild;
}
else if(num<temp->data&&temp->LeftChild!=NULL)
temp = temp->LeftChild;
}
}
删除
今天写删除花了特别多时间,最后还是面向CSDN编程,研究一波后发现了别人很多bug,自己又改动了下。
这里我参考那篇文章的dl就是删除第一个节点的时候会有bug,删除这个函数真的很虚,感觉写的贼菜...
总觉得有很多思路,很多方法,但是写出来就很难看...
void Delete(int num){ BSTNode *temp, *previous;
temp = root;
previous = root;
//获得现在要删除的节点和它前一个节点
while (temp != NULL){ if (temp->data == num)
break;
else if (temp->data > num){
previous = temp;
temp = temp->LeftChild;
}
else{
previous = temp;
temp = temp->RightChild;
}
} if (temp != NULL){ if (temp->LeftChild == NULL){ //要删的结点的左孩子为空的情况 if (temp->RightChild==NULL){//右孩子也为空
if(previous==root) root = NULL; //如果是头结点只需把roor设为NULL
else{
previous->LeftChild==temp? previous->LeftChild = NULL: previous->RightChild = NULL;
delete temp;
}
}
else{//有右孩子,判断该节点是不是根节点或者是上一个节点的什么孩子 if(temp==root) root=root->RightChild;
else previous->LeftChild==temp ? previous->LeftChild=temp->RightChild :previous->RightChild=temp->RightChild;
delete temp;
}
}
else if (temp->RightChild == NULL){ //要删的结点的右孩子为空的情况,但是有左孩子 if(temp=root) root = root->LeftChild;
else previous->LeftChild == temp ? previous->LeftChild=temp->LeftChild :previous->RightChild=temp->LeftChild;
delete temp;
}
else{ //要删的结点的左、右孩子都不为空的情况
//把右子树最小节点的值赋给当前节点,删去右子树最小节点 ,右子树最小节点的右节点顶替原最小节点位置
BSTNode *right_min = temp->RightChild;
previous = right_min; while (right_min->LeftChild != NULL){ //找到右子树最小结点 previous = right_min;
right_min = right_min->LeftChild;
} temp->data = right_min->data; //最小结点的值赋给要删除的结点 if(right_min == previous){
temp->RightChild=right_min->RightChild;
}
else{
previous->LeftChild = right_min->RightChild;
}
delete right_min; //删除右子树的最小结点
}
}
}
插入、查找、删除样例如下:
/*
1
6
22 33 55 66 11 44
3
77
50
10
*/
/*1
6
22 33 55 66 11 44
7
11
22
33
44
55
66
77
*/
/*
1
6
22 33 55 66 11 44
3
66
22
77
*/
最后全部代码如下:
#include<iostream>
using namespace std;
//BST节点
struct BSTNode{
int data;
BSTNode *RightChild;
BSTNode *LeftChild;
BSTNode(){
RightChild = NULL;
LeftChild = NULL;
}
}; class BST{ private:
BSTNode *root;//根节点
void InOrder(BSTNode *t){//中序遍历
if(t!=NULL){
InOrder(t->LeftChild);
cout<<t->data<<" ";
InOrder(t->RightChild);
}
}
public: BST(){
} ~BST(){
} void creatBST(int num[],int n){ root = new BSTNode();
root->data = num[0]; for(int i=1;i<n;i++)
this->Insert(num[i]);
} void InOrder(){
if(root){
InOrder(root);
cout<<endl;
}
else
cout<<"No elements"<<endl;
} void Insert(int num){ BSTNode *temp = root; while(1){
if(num>temp->data){
if(temp->RightChild!=NULL){
temp=temp->RightChild;
}
else{
temp->RightChild = new BSTNode();
temp->RightChild->data = num;
break;
}
}
else{
if(temp->LeftChild!=NULL){
temp=temp->LeftChild;
}
else{
temp->LeftChild = new BSTNode();
temp->LeftChild->data = num;
break;
}
}
}
} int Find(int num){ BSTNode *temp = root; int sum=0; while(1){
if(temp->RightChild==NULL&&temp->LeftChild==NULL&&num!=temp->data){
return -1;
}
sum++;
if(num==temp->data){
return sum;
}
else if(num>temp->data&&temp->RightChild!=NULL){
temp=temp->RightChild;
}
else if(num<temp->data&&temp->LeftChild!=NULL)
temp = temp->LeftChild;
}
} void Delete(int num){ BSTNode *temp, *previous;
temp = root;
previous = root;
//获得现在要删除的节点和它前一个节点
while (temp != NULL){ if (temp->data == num)
break;
else if (temp->data > num){
previous = temp;
temp = temp->LeftChild;
}
else{
previous = temp;
temp = temp->RightChild;
}
} if (temp != NULL){ if (temp->LeftChild == NULL){ //要删的结点的左孩子为空的情况 if (temp->RightChild==NULL){//右孩子也为空
if(previous==root) root = NULL; //如果是头结点只需把roor设为NULL
else{
previous->LeftChild==temp? previous->LeftChild = NULL: previous->RightChild = NULL;
delete temp;
}
}
else{//有右孩子,判断该节点是不是根节点或者是上一个节点的什么孩子 if(temp==root) root=root->RightChild;
else previous->LeftChild==temp ? previous->LeftChild=temp->RightChild :previous->RightChild=temp->RightChild;
delete temp;
}
}
else if (temp->RightChild == NULL){ //要删的结点的右孩子为空的情况,但是有左孩子 if(temp=root) root = root->LeftChild;
else previous->LeftChild == temp ? previous->LeftChild=temp->LeftChild :previous->RightChild=temp->LeftChild;
delete temp;
}
else{ //要删的结点的左、右孩子都不为空的情况
//把右子树最小节点的值赋给当前节点,删去右子树最小节点 ,右子树最小节点的右节点顶替原最小节点位置
BSTNode *right_min = temp->RightChild;
previous = right_min; while (right_min->LeftChild != NULL){ //找到右子树最小结点 previous = right_min;
right_min = right_min->LeftChild;
} temp->data = right_min->data; //最小结点的值赋给要删除的结点 if(right_min == previous){
temp->RightChild=right_min->RightChild;
}
else{
previous->LeftChild = right_min->RightChild;
}
delete right_min; //删除右子树的最小结点
}
}
}
}; int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int num[100];
for(int i=0;i<n;i++)
cin>>num[i]; BST *bst = new BST();
bst->creatBST(num,n);
bst->InOrder(); int m;
cin>>m;
int b[100];
for(int i=0;i<m;i++){
cin>>b[i];
//bst->Insert(b[i]);
//cout<<bst->Find(b[i])<<endl;
bst->Delete(b[i]);
bst->InOrder(); }
}
}
DS-二叉排序树的插入、查找和删除的更多相关文章
- Java实现二叉排序树的插入、查找、删除
import java.util.Random; /** * 二叉排序树(又称二叉查找树) * (1)能够是一颗空树 * (2)若左子树不空,则左子树上全部的结点的值均小于她的根节点的值 * (3)若 ...
- 【数据结构】——搜索二叉树的插入,查找和删除(递归&非递归)
一.搜索二叉树的插入,查找,删除 简单说说搜索二叉树概念: 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右 ...
- 数据结构系列之2-3-4树的插入、查找、删除和遍历完整版源代码实现与分析(dart语言实现)
本文属于原创,转载请注明来源. 在上一篇博文中,详细介绍了2-3树的操作(具体地址:https://www.cnblogs.com/outerspace/p/10861488.html),那么对于更多 ...
- jQuery中的查找节点、创建节点、插入节点、删除节点、替换节点、复制节点操作方法
jQuery操作节点我们可以分六点来讲,查找节点.创建节点.插入节点.删除节点.替换节点.复制节点. 一.查找节点 text() - 设置或返回所选元素的文本内容 ,html() - 设置或返回所 ...
- mysql插入数据与删除重复记录的几个例子(收藏)
mysql插入数据与删除重复记录的几个例子 12-26shell脚本实现mysql数据的批量插入 12-26mysql循环语句插入数据的例子 12-26mysql批量插入数据(insert into ...
- SQL重复记录处理(查找,过滤,删除)
SQL重复记录处理(查找,过滤,删除) ID int Title nvarchar(50) AddDate datetime 数据 www.2cto.com ID ...
- 有关文件夹与文件的查找,删除等功能 在 os 模块中实现
最近在写的程序频繁地与文件操作打交道,这块比较弱,还好在百度上找到一篇不错的文章,这是原文传送门,我对原文稍做了些改动. 有关文件夹与文件的查找,删除等功能 在 os 模块中实现.使用时需先导入这个模 ...
- STL中vector的赋值,遍历,查找,删除,自定义排序——sort,push_back,find,erase
今天学习网络编程,那个程序中利用了STL中的sort,push_back,erase,自己没有接触过,今天学习一下,写了一个简单的学习程序.编译环境是VC6.0 这个程序使用了vect ...
- Java中数组的几个常用算法:插入算法,删除算法,冒泡排序算法
前言: 在Java中我们常常会用数组,提到数组就不得不介绍数组中常用到的几个算法. 有插入算法,删除算法,冒泡排序算法等. 在学习这几个数组的算法前,我们先来了解一下关于数组一些基本知识. 数组的基本 ...
随机推荐
- 大数据数据库HBase(一)——架构原理
一.HBase简介 1.1.Hadoop生态系统 1.2.非关系型数据库知识面扩展 Cassandra hbase mongodb Couchdb,文件存储数据库 Neo4j非关系型图数据库 1.3 ...
- MixConv
深度分离卷积一般使用的是3*3的卷积核,这篇论文在深度分离卷积时使用了多种卷积核,并验证了其有效性 1.大的卷积核能提高模型的准确性,但也不是越大越好.如下,k=9时,精度逐渐降低 2. mixCon ...
- fhq_treap || BZOJ 3224: Tyvj 1728 普通平衡树 || Luogu P3369 【模板】普通平衡树
题面:[模板]普通平衡树 代码: #include<cstdio> #include<cstring> #include<iostream> #include< ...
- C++中vecotr表示二维数组并自己实现一个Grid类
1 C++中使用vector来表示二维数组 声明一个二维数组: vector<vector<int>> dp(row, vector<int>(col)); 将变量 ...
- Linux openssh8.0p1升级步骤(shell版本)
运维自动化时代,手动升级太徒劳了,为了提高效率及准确率,自动化安装是必备的. 下面是通过shell写的脚本.也可以将其应用到ansible上. 准备好安装文件: openssh-8.0p1.tar.g ...
- spring 管理bean
目录结构: Person.java package com.wss.entity; import com.wss.service.doHomeWork; public class Person { p ...
- python-抽象类和抽象方法
需要模块 import abc 抽象类不能实例化 import abc class Animal(metaclass=abc.ABCMeta): #抽象类 @abc.abstractmethod # ...
- 【ZJOI2008】树的统计
题目 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: ...
- 6359. 【NOIP2019模拟2019.9.15】小ω的树(tree)(定期重构)
题目描述 题解 qy的毒瘤题 CSP搞这种码农题当场手撕出题人 先按照边权从大到小建重构树,然后40%暴力修改+查找即可 100%可以定期重构+平衡规划,每次把B个询问拉出来建虚树,在虚树上暴力维护每 ...
- 用二叉树进行排序 x (从小到大)
先输入n,表示拥有多少个数: 第二行输入1-n个数,然后开始排序 输出从小到大的排序. ----------------------------------------------代码~------- ...