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中我们常常会用数组,提到数组就不得不介绍数组中常用到的几个算法. 有插入算法,删除算法,冒泡排序算法等. 在学习这几个数组的算法前,我们先来了解一下关于数组一些基本知识. 数组的基本 ...
随机推荐
- JavaWeb中的文件上传和下载功能的实现
导入相关支持jar包:commons-fileupload.jar,commons-io.jar 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上 ...
- 多个excel文件内容合并到一个excel文件的多个sheet的小程序
# -*- coding:utf-8 -*- import xlrd, xlsxwriter # 待合并excelallxls = ["D:\\excelcs\\***.xlsx" ...
- 面试题常考&必考之--js中的call()和apply()
apply: 接受两个参数,第一个参数是要绑定给this的值,第二个参数是一个参数数组.当第一个参数为null.undefined的时候,默认指向window. call: 第一个参数是要绑定给thi ...
- 寻找的常用webstorm快捷键
1. 必备快捷键 Ctrl+/:注释当前行 Ctrl+Shift+/:当前位置插入注释 Ctrl+Alt+/:块注释,并Focus到首行,写注释说明用的 Ctrl+Shift+A:选择当前标签前后,修 ...
- JDK,JRE与JVM浅析
JAVA的两个特性: 1, 开源-指的是源代码免费 2,跨平台(可移植性好) 跨平台:是指跨操作系统 JVM(java virtual machine,java虚拟机) JVM就像是两国谈判时的使者充 ...
- tapmode="hover"属性
.hover{ opacity: .; } <span tapmode="hover" onclick="fnOpen()">open</sp ...
- Software-Defined Networking: A Comprehensive Survey
文章名称:Software-Defined Networking: A Comprehensive Survey 文章来源:Proceedings of the IEEE ( Volume: 103 ...
- IDEA插件之自动查找bug工具
打开idea 插件搜索界面 输入 FindBugs-IDEA,安装完成后重启,选中要查找的包,右键找到对应的 FindBugs就可以开始进行自动扫描了
- php简单随机实现发红包程序
前言: 使用PHP发红包,当我们输入红包数量和总金额后,PHP会根据这两个值进行随机分配每个金额,保证每个人都能领取到一个红包,每个红包金额不等,就是要求红包金额要有差异,所有红包金额总额应该等于总金 ...
- WebPack Task Runner
https://marketplace.visualstudio.com/items?itemName=MadsKristensen.WebPackTaskRunner New to WebPack? ...