1.二叉排序树:插入和删除元素的效率不错,同时查找的效率也不错

.    通过中序遍历,可使得排序变为从小到大的序列:46--67--70--99--104--105--109--111--115

1.1二叉排序树的概念

算法代码:

#include <iostream>
#include <stdlib.h>
#include<string>
#include<cstring>
using namespace std;
int posi = 0;
class Tnode
{
public:string data; Tnode* lnext;Tnode* rnext;
};
bool CreBTree(Tnode *&T) //前序遍历创建二叉树
{//前序遍历输入数组astring a[18] = { "70","67","46","#","#","#","105","104","99","#","#","#","115","111","109","#" ,"#" ,"#" };if (a[posi] == "#"){posi++;T = NULL;}else{   if (posi == 18){return true;}T = new Tnode();//BUG: T = (Tnode*)malloc(sizeof(Tnode));T->data = a[posi++];CreBTree(T->lnext);CreBTree(T->rnext);}}
void MidTree(Tnode* &T)//中序遍历二叉树
{if (T){MidTree(T->lnext);cout << T->data <<" ";MidTree(T->rnext);}
}//二叉排序树
//T为根节点地址;key为要查找的关键字;f指向T的双亲节点,初始值为NULL
//若查找成功,p指向该元素节点,返回true;若失败,p指向查找路径上访问的最后一个节点,返回false
bool Search_BST(Tnode*& T, int key, Tnode*& f, Tnode* &p)
{//string s = to_string(key);if (!T)//查找不成功{p = f; //p获取T的双亲节点return false;}else if (key == atoi(T->data.c_str())) //查找成功,将string转化为int类进行关键字的比较{p = T;  //p获取当前节点的位置return true;}else if (key < atoi(T->data.c_str())){return Search_BST(T->lnext, key, T, p);//在左子树继续查找}else {return Search_BST(T->rnext, key, T, p);//在又子树继续查找}
}//键字没找到后,插入带关键字的新节点操作
bool BST_insert(Tnode*& T, int key)
{string str_key = to_string(key);Tnode* f = NULL;Tnode* p=NULL;if (!Search_BST(T, key, f, p))//没找到查找,则插入{//创建节点Tnode* s = new Tnode();s->data = str_key;s->lnext = NULL;s->rnext = NULL;if (!p)//若树为空{*&T = s;}else if (key < atoi(p->data.c_str())){p->lnext = s;}else{p->rnext = s;}return true;}else //找到了{return false;}
}int main()
{Tnode* T;cout << "以前序遍历的方式(先双亲--左子树--右子树)输入二叉树节点,用#表示无叶节点:";CreBTree(T);MidTree(T);cout << endl;if (BST_insert(T, 1)) //TRUE{cout << "Insert SUCCEED" << endl;}else{cout << "Find it" << endl;}MidTree(T);//std::cout << "Hello World!\n";}

输出结果

代码解析:代码中有1个结构体 和 4个函数

1.二叉树节点结构体

结构体用来描述节点

2.前序遍历创建二叉树:bool CreBTree(Tnode *&T) //头节点T 的指针,作为参数

定义一个string 数组a,用来存放节点的data,如果data没有数据,则用“#”代替,之后再用if语句把“#”所在的节点T置为NULL;

若a数组有数据,则申请内存(注意要用new申请内存,用malloc申请内存,string类型的结构体成员会出现内存溢出),用递归的方式对左子树和右子树进行创建。

创建的二叉排序树如下图:

3.前序遍历二叉树:void PreTree(Tnode* &T) //头指针T作为参数

如果存在头结点T;则进行前序遍历

前序遍历规则:(递归进行访问)先双亲节点,再左节点,再右节点

4.查找二叉树中的关键元素节点:bool Search_BST(Tnode*& T, int key, Tnode*& f, Tnode* &p) //若查找成功,p指向该元素节点,返回true;若失败,p指向查找路径上访问的最后一个节点,返回false

输出参数:T:头结点指针; key关键词;f:用于指向T的双亲节点,初始值为NULL;p:的作用是:若查找成功,p指向该元素节点,返回true;若失败,p指向查找路径上访问的最后一个节点,返回false

采用递归的方式进行查找:

  • 如果当已经搜索到叶节点了,如果找不到带关键词的节点,此时的叶节点T 都是=NULL的;则用p获取T的双亲节点,返回false。(这也是递归结束标志)
  • 否则如果搜索到叶节点,则用p获取当前节点T的地址,返回true
  • 否则如果key小于当前节点的data,则在左子树进行递归查找,并将当前节点T作为下一个节点的双亲节点,传入到 f参数位置
  • 否则,在右子树进行递归查找,并将当前节点T作为下一个节点的双亲节点,传入到 f参数位置

5.关键字没找到后,插入带关键字的新节点操作:bool BST_insert(Tnode*& T, int key)  //

如果未查找到关键字,则返回true

{

创建新节点;

如果树为空,则零新节点作为根节点

否则如果key< 上一个节点p的data(注意这里不是T->data, 而是p->data!!),将新节点s插入左子树

否则将新节点s插入左子树

}

否则搜索到关键字,则返回false

算法优化代码:

通过插入进行创建二叉排序树,而不是通过前序遍历来创建二叉排序树

// SearchBST_2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <stdlib.h>
#include<string>
#include<cstring>
using namespace std;
int posi = 0;
class Tnode
{
public:int data;Tnode* lnext;Tnode* rnext;
};void MidTree(Tnode*& T)//中序遍历二叉树
{if (T){MidTree(T->lnext);cout << T->data << " ";MidTree(T->rnext);}
}//二叉排序树
//T为根节点地址;key为要查找的关键字;f指向T的双亲节点,初始值为NULL
//若查找成功,p指向该元素节点,返回true;若失败,p指向查找路径上访问的最后一个节点,返回false
bool Search_BST(Tnode*& T, int key, Tnode*& f, Tnode*& p)
{//string s = to_string(key);if (!T)//查找不成功{p = f; //p获取T的双亲节点return false;}else if (key == T->data) //查找成功,将string转化为int类进行关键字的比较{p = T;  //p获取当前节点的位置return true;}else if (key < T->data){return Search_BST(T->lnext, key, T, p);//在左子树继续查找}else{return Search_BST(T->rnext, key, T, p);//在又子树继续查找}
}//键字没找到后,插入带关键字的新节点操作,返回false;有关键字则返回true,
bool BST_insert(Tnode*& T, int key)
{Tnode* f = NULL;Tnode* p = NULL;if (!Search_BST(T, key, f, p))//找不到{//创建新节点Tnode* s = new Tnode();s->data = key;s->lnext = NULL;s->rnext = NULL;if (!p)//若无根节点{T = s;}else if (key < p->data){p->lnext = s;}else if (key > p->data){p->rnext = s;}elsereturn false;}elsereturn true;
}int main()
{Tnode* T=NULL;int c[9] = {70,105,115,104,67,46,99,111,109};for (int i = 0; i < 9; i++){BST_insert(T, c[i]); //用插入的方式进行二叉排序的创建}cout << "二叉排序为:";MidTree(T);
}

输出结果为:

二叉排序树的节点删除:

比如有如下二叉排序树

中序遍历输出的结果为:46--67--70--99--100--103--104--105--108--110--112--115

有3中删除情况:

1.要删除的节点为叶子节点:叶子节点可以直接删除

2.删除有左子树,无右子树的节点: 删除掉节点67,后面的节点46直接顶上去。如下图所示

4.删除有右子树,无左子树的节点P

3.删除及有左子树,又有右子树的节点105:只需要将104顶到105的位置,103顶到104的位置,只需要将data改变,节点的位置不用改动

算法代码

bool Delete(Tnode*& P)
{Tnode* Q = NULL; //用来存放:待删除节点的双亲节点Tnode* S = NULL; //每次迭代用到的节点//第一种情况,要删除的节点P是叶节点 or 节点P是有左子树,没有右子树if (P->rnext == NULL){Q = P;P = P->lnext; //左子树往上顶free(Q);}else if (P->lnext == NULL)//第二种情况,节点P的只有一个右子树,左子树为NULL, {Q = P;P = P->rnext;//右子树往上顶free(Q);}else//左子树不为NULL, 右子树不为NULL (这段代码太强了){Q = P; S = P->lnext;while (S->rnext){Q = S;S = S->rnext;}P->data = S->data;if (Q != P){Q->rnext = S->lnext;}else{Q->lnext = S->lnext;}free(S);}
}//删除节点,T:根节点,key关键词,
//若不存在要删除的关键字,返回false;存在则删除
bool DeletBST(Tnode*& T, int key)
{if (!T){return false;}else if (key == T->data){return Delete(T);}else if (key < T->data){return DeletBST(T->lnext, key);}else{return DeletBST(T->rnext, key);}
}

代码分析:

1. bool DeletBST(Tnode*& T, int key)  //删除带关键词的节点

先递归查找关键词key,如果都一直到叶节点都没有找到key,则返回false;

否则如果找到key,则返回 删除;

否则如果key小于节点T的data,继续递归向左子树找;

否则如果key大于节点T的data,递归向右子树查找

2. bool Delete(Tnode*& P)  //找到要删除的关键词节点后,将地址传入,P是要删除的关键词节点的地址

第一种情况:P是有左子树,无右子树,或者 P无左子树,也无右子树;如下图所示,比如要删除67或108

则用Q=P; P=P->lnex;  free(Q);

第二种情况:节点P的只有一个右子树,左子树为NULL, 如下图所示:比如要删除20

第三种情况:左子树不为NULL, 右子树不为NULL,如下图所示,比如要删除105 ,其中还包含了两种情况

情况一:100节点存在右子树分支  ----->目的是变为:

情况二:100节点不存右子树分支 ----->目的是变为: 

相关代码

    else//左子树不为NULL, 右子树不为NULL (这段代码太强了),不通过删除关键词节点,而是采用data值进行传递起到data值覆盖的作用,最后删除{Q = P; S = P->lnext; //S赋值为P的左节点while (S->rnext)   //对S的右子树进行迭代{Q = S; //使得Q始终是指向S的双亲节点S = S->rnext;}P->data = S->data; //将S->data直接覆盖掉P->dataif (Q != P) //如果S存在右子树,直接{Q->rnext = S->lnext; //让Q->rnext 指向S->lnext}else //如果S不存在右子树,即不存在104的右子树分支{Q->lnext = S->lnext; //让Q->lnext 指向S->lnext}free(S); //释放S 有两种情况,第一种S处于104位置,第二种S处于100的位置}
}

整体的代码

// SearchBST_2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <stdlib.h>
#include<string>
#include<cstring>
using namespace std;
int posi = 0;
class Tnode
{
public:int data;Tnode* lnext;Tnode* rnext;
};void MidTree(Tnode*& T)//中序遍历二叉树
{if (T){MidTree(T->lnext);cout << T->data << " ";MidTree(T->rnext);}
}//二叉排序树
//T为根节点地址;key为要查找的关键字;f指向T的双亲节点,初始值为NULL
//若查找成功,p指向该元素节点,返回true;若失败,p指向查找路径上访问的最后一个节点,返回false
bool Search_BST(Tnode*& T, int key, Tnode*& f, Tnode*& p)
{//string s = to_string(key);if (!T)//查找不成功{p = f; //p获取T的双亲节点return false;}else if (key == T->data) //查找成功,将string转化为int类进行关键字的比较{p = T;  //p获取当前节点的位置return true;}else if (key < T->data){return Search_BST(T->lnext, key, T, p);//在左子树继续查找}else{return Search_BST(T->rnext, key, T, p);//在又子树继续查找}
}//键字没找到后,插入带关键字的新节点操作,返回false;有关键字则返回true,
bool BST_insert(Tnode*& T, int key)
{Tnode* f = NULL;Tnode* p = NULL;if (!Search_BST(T, key, f, p))//找不到{//创建新节点Tnode* s = new Tnode();s->data = key;s->lnext = NULL;s->rnext = NULL;if (!p)//若无根节点{T = s;}else if (key < p->data){p->lnext = s;}else if (key > p->data){p->rnext = s;}elsereturn false;}elsereturn true;
}bool Delete(Tnode*& P)
{Tnode* Q = NULL; //用来存放:待删除节点的双亲节点Tnode* S = NULL; //每次迭代用到的节点//第一种情况,要删除的节点P是叶节点 or 节点P是有左子树,没有右子树if (P->rnext == NULL){Q = P;P = P->lnext; //左子树往上顶free(Q);}else if (P->lnext == NULL)//第二种情况,节点P的只有一个右子树,左子树为NULL, {Q = P;P = P->rnext;//右子树往上顶free(Q);}else//左子树不为NULL, 右子树不为NULL (这段代码太强了),不通过删除关键词节点,而是采用data值进行传递起到data值覆盖的作用,最后删除{Q = P; S = P->lnext; //S赋值为P的左节点while (S->rnext)   //对S的右子树进行迭代{Q = S; //使得Q始终是指向S的双亲节点S = S->rnext;}P->data = S->data; //将S->data直接覆盖掉P->dataif (Q != P) //如果S存在右子树,直接{Q->rnext = S->lnext; //让Q->rnext 指向S->lnext}else //如果S不存在右子树,即不存在104的右子树分支{Q->lnext = S->lnext; //让Q->lnext 指向S->lnext}free(S); //释放S 有两种情况,第一种S处于104位置,第二种S处于100的位置}return true;
}//删除节点,T:根节点,key关键词,
//若不存在要删除的关键字,返回false;存在则删除
bool DeletBST(Tnode*& T, int key)
{if (!T){return false;}else if (key == T->data){return Delete(T);}else if (key < T->data){return DeletBST(T->lnext, key);}else{return DeletBST(T->rnext, key);}
}int main()
{Tnode* T=NULL;int t;int c[9] = {70,105,115,104,67,46,99,111,109};for (int i = 0; i < 9; i++){BST_insert(T, c[i]); //用插入的方式进行二叉排序的创建}cout << "二叉排序为:";MidTree(T);cout << "删除关键词:"; cin >> t;DeletBST(T, t);cout << "二叉排序为:";MidTree(T);
}

9.查找算法--二叉排序树相关推荐

  1. 【查找算法】二叉排序树查找法

    本篇文章将介绍二叉排序树的查找算法. 文章目录 何为二叉排序树查找? 查找算法实现 查找效率分析 二叉排序树的插入操作 二叉排序树的生成操作 二叉排序树的删除操作 何为二叉排序树查找? 上篇文章我们学 ...

  2. 查找算法系列之复杂算法:二叉排序树BST

    前面总结了顺序查找,二分查找,分块查找算法,此篇博文将详解介绍二叉排序算法(Binary Sort Tree). 在介绍二叉排序算法之前,首先介绍什么事二叉排序树(BST). 首先从二叉树讲起: 1. ...

  3. 数据结构排序、查找算法

    前言 这是数据结构的实验四的题目. 为了自己能在繁杂的文件中顺利.快速地找到自己熟悉的排序.查找算法代码,故借CSDN平台存放本人写的代码.另外,还请有缘看到此文章的同行们能多多指点. 非常感谢. 1 ...

  4. 数据结构-常用的查找算法

    总第124篇/张俊红 本篇讲讲数据结构里面常用的几个查找算法,数据结构理论篇系列差不多接近尾声了,接下来会分享一些比较特殊的概念,比如KMP.郝夫曼树等等,讲完概念以后会进入刷题阶段.刷题会用Pyth ...

  5. 数据结构中基本查找算法总结

    原文地址:https://www.cnblogs.com/xuzhp/p/4638937.html 基本查找算法    一.查找的基本概念 查找,也可称检索,是在大量的数据元素中找到某个特定的数据元素 ...

  6. 减治法在查找算法中的应用(JAVA)--二叉查找树的查找、插入、删除

    减治法在查找算法中的应用 二叉查找树的查找与插入: 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于或等于它的根节点的值: (2)若右子树不空, ...

  7. 【数据结构与算法】比较法分析查找算法与查找结构

    基本的查找技术: 线性表的查找技术 顺序查找 分块查找 二分查找(折半查找) 插值查找 树表的查找技术 二叉排序树 平衡二叉树 B树(B+树.B-树等) 散列表的查找技术 开散列表 闭散列表 顺序查找 ...

  8. java二分查找法视频_078-二分查找算法思路图解

    2.网上数据结构和算法的课程不少,但存在两个问题: 1)授课方式单一,大多是照着代码念一遍,数据结构和算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了 2) ...

  9. 折半查找和二叉排序树的时间性能_详解二叉排序树(基础篇)

    前言 我们的线性表有2种,无序线性表和有序线性表. 无序线性表正如其名,它里面的数据是无序的,因为这个表不用维护什么东西,所有它的插入和删除操作的效率也不错..但是,正因为他是无序的,查找起来就很废时 ...

最新文章

  1. OpenCvSharp_FindContours函数参数详解
  2. iOS开发那些事-表视图UI设计模式
  3. Linux操作系统监视NVIDIA的GPU使用情况
  4. Python中super的用法
  5. Docker安装RabbitMQ(docker-compose.yml)
  6. elasticjob 分片策略
  7. dimension and x,y,z components
  8. servlet执行流程代码分析
  9. 安装mysql5.7数据库_使用MySQL的yum源安装MySQL5.7数据库的方法
  10. 学有小成-php基础语法-06
  11. 一分钟教你解决前端分流问题
  12. Nvme协议固态装纯净win10系统
  13. 实现折叠工具栏CollapsingToolbarLayout(折叠工具栏布局)
  14. 介绍兴趣爱好的网页html,介绍兴趣爱好的作文5篇
  15. Vs2008调试慢的问题
  16. 竖流式沉淀池集水槽设计计算_竖流沉淀池设计计算书.doc
  17. GrabCut提取图像前景色MATLAB代码实现(含解释说明)
  18. Could not build wheels for xx which use PEP 517 and cannot be installed directly
  19. 修复打不开计算机管理,win10系统设备管理器打不开的修复技巧
  20. 转自周金涛:一辈子有三次暴富机会,最近的一次在2019年?2018年你要怎么做? (2018-02-21 17:49:17)...

热门文章

  1. 拼多多搜索词统计 API接口操作展示说明
  2. 【知识兔】Excel中的F1~F12快捷键,你还不会?强大到爆~
  3. 超实用,这是我见过最全面的python入门教程,高中生不要错过
  4. Herman miller Aeron 一代 气压杆(气压棒,气柱)更换笔记(电脑椅中的劳斯莱斯)
  5. Vue实现图形化积木式编程(十二)
  6. 【SVAC2.0】国家安防监控SVAC2.0标准支持特性
  7. 入门UVM验证方法学
  8. 如何从Google Play下载应用到电脑
  9. Rational Rose2007的安装
  10. Android工作日志