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-二叉排序树的插入、查找和删除的更多相关文章

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

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

  2. 【数据结构】——搜索二叉树的插入,查找和删除(递归&非递归)

    一.搜索二叉树的插入,查找,删除 简单说说搜索二叉树概念: 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右 ...

  3. 数据结构系列之2-3-4树的插入、查找、删除和遍历完整版源代码实现与分析(dart语言实现)

    本文属于原创,转载请注明来源. 在上一篇博文中,详细介绍了2-3树的操作(具体地址:https://www.cnblogs.com/outerspace/p/10861488.html),那么对于更多 ...

  4. jQuery中的查找节点、创建节点、插入节点、删除节点、替换节点、复制节点操作方法

    jQuery操作节点我们可以分六点来讲,查找节点.创建节点.插入节点.删除节点.替换节点.复制节点. 一.查找节点 text() - 设置或返回所选元素的文本内容   ,html() - 设置或返回所 ...

  5. mysql插入数据与删除重复记录的几个例子(收藏)

    mysql插入数据与删除重复记录的几个例子 12-26shell脚本实现mysql数据的批量插入 12-26mysql循环语句插入数据的例子 12-26mysql批量插入数据(insert into ...

  6. SQL重复记录处理(查找,过滤,删除)

    SQL重复记录处理(查找,过滤,删除)     ID int    Title nvarchar(50)    AddDate datetime    数据  www.2cto.com     ID ...

  7. 有关文件夹与文件的查找,删除等功能 在 os 模块中实现

    最近在写的程序频繁地与文件操作打交道,这块比较弱,还好在百度上找到一篇不错的文章,这是原文传送门,我对原文稍做了些改动. 有关文件夹与文件的查找,删除等功能 在 os 模块中实现.使用时需先导入这个模 ...

  8. STL中vector的赋值,遍历,查找,删除,自定义排序——sort,push_back,find,erase

    今天学习网络编程,那个程序中利用了STL中的sort,push_back,erase,自己没有接触过,今天学习一下,写了一个简单的学习程序.编译环境是VC6.0         这个程序使用了vect ...

  9. Java中数组的几个常用算法:插入算法,删除算法,冒泡排序算法

    前言: 在Java中我们常常会用数组,提到数组就不得不介绍数组中常用到的几个算法. 有插入算法,删除算法,冒泡排序算法等. 在学习这几个数组的算法前,我们先来了解一下关于数组一些基本知识. 数组的基本 ...

随机推荐

  1. 004-sed 命令使用

    sed 命令使用 主要作用是用来将数据进行选取,替换,删除,新增的命令,与vim类似 选项: -n : 只显示经过sed处理的数据,打印到屏幕 -e: 运行多个条件同时运行 -i: 直接修改文件 -p ...

  2. IsNumeric 函数

    VB IsNumeric 判断数字函数功能详解: IsNumeric 函数 函数功能:     返回 Boolean 值,指出表达式的运算结果是否为数. 函数语法:     IsNumeric (ex ...

  3. python3-访问限制

    在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑. 但是,从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的na ...

  4. Halcon WPF C#采集图像区域灰度值

    源码下载地址:https://github.com/lizhiqiang0204/ImageGray.git Halcon代码如下: *读取图片,转换成灰度图片 read_image (Image1, ...

  5. Zookeeper学习笔记(下)

    这是ZK学习笔记的下篇, 主要希望可以分享一些 ZK 的应用以及其应用原理 我本人的学习告一段落, 不过还遗留了一些ZK相关的任务开发和性能测试的任务, 留待以后完成之后再通过其他文章来进行分享了 Z ...

  6. 1.使用kubeadm安装kubernetes

    一.环境准备 所有规划主机(一台master,两台node)均需操作 1.关闭防火墙,selinux [root@node1 ~]# systemctl stop firewalld [root@no ...

  7. Jdbc连接数据库基本步骤详解_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 Jdbc连接数据库的基本步骤,供大家参考,具体内容如下 package demo.jdbc; import java.s ...

  8. Top 8 Diagrams for Understanding Java

    Reference: http://www.programcreek.com/2013/09/top-8-diagrams-for-understanding-java/ A diagram is s ...

  9. HTML DOM方法

    一.HTML DOM的作用 HTML DOM方法是我们可以在节点(html元素)上执行的动作. HTML DOM属性是我们可以在节点(html元素)设置和修改的值. 编程接口: 可以通过JavaScr ...

  10. PHP入门培训教程 php中的时间处理

    php中的时间处理 PHP入门培训教程 兄弟连PHP培训 小编整理的 php中的时间处理: <? /** * 转换为UNIX时间戳 */ function gettime($d) { if(is ...