一、数据结构背景+代码变量介绍

  二叉查找树,又名二叉排序树,亦名二叉搜索树

  它满足以下定义:

    1、任意节点的子树又是一颗二叉查找树,且左子树的每个节点均小于该节点,右子树的每个节点均大于该节点。

    2、由1可推出,任意节点的左孩子小于该节点,右孩子大于该节点

      以上讨论的是左(右)孩子(子树)存在的情况

  它的中序遍历是一个升序的排序

  在参考代码中,我们定义有:

    主程序中,k代表插入或删除或查找的节点的值

    root,根节点位置;a[i],第 i 号节点的值;cl[i],第 i 号节点左孩子的位置;cr[i],第 i 号节点右孩子的位置;fa[i],父亲节点位置


二、中序遍历

   中序遍历的求法采用递归,先递归它的左孩子,然后打印当前节点,最后递归它的右孩子(当左或右孩子存在时才进行递归)

  

  如上图的中序遍历为 DBEAFC

  时间复杂度O(n)

  1. void mid(int x)
  2. {
  3. if (time[cl[x]]!=) mid(cl[x]);
  4. cout<<a[x]<<" ";
  5. if (time[cr[x]]!=) mid(cr[x]);
  6. }
  7.  
  8. 主程序中:mid(root);

三、插入节点

  我们采用遇到相同的节点,使该节点计数器+1的办法

  先从根节点出发:

    1、若当前节点小于插入的数,则递归进入其左儿子

                   若左儿子计数器为0,即不存在左儿子,则直接将数插入到左儿子

    2、若当前节点大于插入的数,则递归进入其右儿子

                   若右儿子计数器为0,即不存在右儿子,则直接将数插入到右儿子

    3、若当前节点等于插入的数,则直接将该节点计数器+1

样例一

  如上图,将6插入该二叉树

    1、与根节点比较,小于根节点,进入左儿子

    2、与2比较,大于2,进入右儿子

    3、与5比较,大于5,进入右儿子,但因右儿子不存在,所以将6作为其右儿子

样例二

  如上图,将1插入该二叉树:

    1、与根节点比较,小于8,进入左儿子

    2、与2比较,小于2,进入左儿子,但因其左儿子不存在,所以将1作为其左儿子

  时间复杂度O(log2n)

  1. void ins(int i,int x)
  2. {
  3. if (root==)
  4. {
  5. a[]=x;
  6. time[]=root=;
  7. return;
  8. }
  9. if (x<a[i])
  10. {
  11. if (time[cl[i]]==)
  12. {
  13. cl[i]=top>0?s[top--]:++tail;
    a[cl[i]]=x;
  14. fa[cl[i]]=i;
  15. time[cl[i]]++;
  16. cr[cl[i]]=cl[cl[i]]=;
  17. }
  18. else ins(cl[i],x);
  19. }
  20. else if (x>a[i])
  21. {
  22. if (time[cr[i]]==)
  23. {
  24. cr[i]=top>0?s[top--]:++tail;
    26 a[cr[i]]=x;
  25. fa[cr[i]]=i;
  26. time[cr[i]]++;
  27. cr[cr[i]]=cl[cr[i]]=;
  28. }
  29. else ins(cr[i],x);
  30. }
  31. else
  32. {
  33. time[i]++;
  34. }
  35. }
  36.  
  37. 主程序中:ser(root,k); root代表起始位置,k代表插入的值

四、查找节点

  查找类似于插入

  同样从根节点出发,如果遇到了空节点,即计数器等于0的节点,直接返回0,表示未查找到

  若该节点等于查找的值,则返回该节点的位置

  若该节点大于查找的值,则向左儿子递归查找

  若该节点小于查找的值,则向右儿子递归查找

  此处说明,若当前节点为空节点,则说明小于(大于)该节点父亲的值不存在,即未查找到

  查找类似于线段树思想,是一步步向下把范围缩小,直到找到期望的值或无结果

样例一

  如上图,需查找的值为5

    1、查找根节点,5<8,进入左儿子

    2、5>2,进入右儿子

    3、5=5,查找到该节点,返回该节点的位置

  若需查找的值为4时,在第3步会进入其左儿子,又因左儿子为空节点,则返回0,说明未查找到

  时间复杂度O(log2n)

  1. int sea(int i,int x)
  2. {
  3. if (time[i]==) return ;
  4. if (a[i]==x) return i;
  5. else if (a[i]>x) return ser(cl[i],x);
  6. else return ser(cr[i],x);
  7. }
  8.  
  9. 主程序中:sea(root,k); root代表查找的起始位置,k代表查找的值

五、删除节点

  当需要删除节点时,先查找改值所在的位置,然后再进行删除

  如果该节点计数器大于1,则只用把计数器-1

  如果计数器等于1,即删除后该节点不再存在,则根据儿子的数目分为三种情况:

    1、没有儿子:直接将该节点删除

    2、一个儿子:将该节点父亲的左(右)儿子直接指向该节点的唯一的那个儿子

    3、两个儿子:在该节点的右子树中寻找一个最小的值,然后用最小的那个节点替代该节点,最后删除最小的节点

            寻找最小节点具体方法:先将目前节点指向右儿子,然后寻找不断指向目前节点的左儿子,直到没有左儿子为止

            因为需要删除的最小节点肯定没有左儿子,所以只需递归执行第1或第2种情况,即 del(最小节点位置,最小节点的值)具体请参考代码

样例一

  删除9节点:调用查找,查找到9的位置,因为它没有儿子,可直接删除

样例二

  删除5节点:同样查找5节点的位置,发现其有1个孩子,则将 5节点 的 父亲2节点 的 右孩子 指向 5节点 的 孩子6节点,这样就自动删除了5节点

样例三

  删除2节点:

    1、查找到2节点的位置

    2、把最小节点指向其右孩子

    3、不断寻找目前最小节点的左孩子,直到尽头,找到最小节点

    4、将最小节点的信息赋给2节点

    5、按照删除节点的方法删除最小节点4节点

  时间复杂度O(log2n)

  1. void del(int k,int x)
  2. {
  3. int ct=;
  4. if (cl[k]!=) ct++;
  5. if (cr[k]!=) ct++;
  6. time[k]--;
  7. if (time[k]==)
  8. {
  9. if (ct==)
  10. {
  11. s[++top]=k;
    if (k==root)
  12. {
  13. root=time[cr[k]]==?cl[k]:cr[k];
  14. return;
  15. }
  16. if (x<a[fa[k]]) cl[fa[k]]=time[cr[k]]==?cl[k]:cr[k];
  17. else cr[fa[k]]=time[cr[k]]==?cl[k]:cr[k];
  18. }
  19. else if (ct==)
  20. {
  21. int s=cr[k];
  22. if (time[cl[s]]!=) s=cl[s];
  23. time[k]=time[s];
  24. a[k]=a[s];
  25. del(s,a[s]);
  26. }
  27. else s[++top]=k;
    29 }
  28. }
  29.  
  30. 主程序中:del(sea(root,k),k); 先查找到需删除的节点的位置,然后删除k

六、空节点位置栈

  在删除节点的时候,会产生许多空节点

  为了节省空间,我们会开一个栈来保存空节点的位置,当删除某个节点后,把它空出来的位置压入栈中

  当插入节点时,先询问栈顶top是否大于0,若栈中有元素,则把栈中的位置弹出,用该位置存放节点

                      若栈中没有元素,表示前面没有空的位置,则新开一个空间来存放节点,通过保存最大位置数的变量tail来控制最大位置


七、特殊情况

  对于二叉查找树会产生如下图的情况

  则所有操作的时间往往会被卡成线性O(n),而利用平衡二叉树、伸展树、红黑树等等数据结构便会帮我们解决这个问题

版权所有,转载请联系作者,违者必究

QQ:740929894

二叉查找树 _ 二叉排序树 _ 二叉搜索树_C++的更多相关文章

  1. 前序遍历 排序 二叉搜索树 递归函数的数学定义 return 递归函数不能定义为内联函数 f(x0)由f(f(x0))决定

    遍历二叉树   traversing binary tree 线索二叉树 threaded binary tree 线索链表 线索化 1. 二叉树3个基本单元组成:根节点.左子树.右子树 以L.D.R ...

  2. 数据结构☞二叉搜索树BST

    二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它可以是一棵空树,也可以是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它 ...

  3. [BinaryTree] 二叉搜索树(二叉查找树、二叉排序树)

    二叉查找树(BinarySearch Tree,也叫二叉搜索树,或称二叉排序树BinarySort Tree)或者是一棵空树,或者是具有下列性质的二叉树: (1)若它的左子树不为空,则左子树上所有结点 ...

  4. Ex 6_20 最优二叉搜索树..._第六次作业

    假设关键字的总数为n,用c[i,j]表示第i个关键字到第j个关键字的最优二叉查找树的代价,我们的目标是求c[0,n-1].要求c[i,j],首先要从第i个关键字到第j个关键字中选一个出来作为根结点,选 ...

  5. 数据结构学习笔记_树(二叉搜索树,B-树,B+树,B*树)

    一.查找二叉树(二叉搜索树BST) 1.查找二叉树的性质 1).所有非叶子结点至多拥有两个儿子(Left和Right): 2).所有结点存储一个关键字: 3).非叶子结点的左指针指向小于其关键字的子树 ...

  6. PAT树_层序遍历叶节点、中序建树后序输出、AVL树的根、二叉树路径存在性判定、奇妙的完全二叉搜索树、最小堆路径、文件路由

    03-树1. List Leaves (25) Given a tree, you are supposed to list all the leaves in the order of top do ...

  7. 【Java】 大话数据结构(11) 查找算法(2)(二叉排序树/二叉搜索树)

    本文根据<大话数据结构>一书,实现了Java版的二叉排序树/二叉搜索树. 二叉排序树介绍 在上篇博客中,顺序表的插入和删除效率还可以,但查找效率很低:而有序线性表中,可以使用折半.插值.斐 ...

  8. 《数据结构与算法分析——C语言描述》ADT实现(NO.03) : 二叉搜索树/二叉查找树(Binary Search Tree)

    二叉搜索树(Binary Search Tree),又名二叉查找树.二叉排序树,是一种简单的二叉树.它的特点是每一个结点的左(右)子树各结点的元素一定小于(大于)该结点的元素.将该树用于查找时,由于二 ...

  9. 判断一棵树是否为二叉搜索树(二叉排序树) python

    输入一棵树,判断这棵树是否为二叉搜索树.首先要知道什么是排序二叉树,二叉排序树是这样定义的,二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的 ...

随机推荐

  1. django中cookies和session

    django中cookies和session是两个经常使用的用户认证工具.都是类似于字典的数据类型,都是request的内部属性 cookies的读写方法 cookies读,比如username us ...

  2. java与数据库交互常用到的一些方法

    下面我整理了一下java中常用的几个与数据库交互的常用方法,仅供参考: 1.执行SQL(dao层的实现类中) (1)SQL查询: //import org.hibernate.Query;//impo ...

  3. Android开发12——Andorid中操作数据库的insert的两种方法以及nullColumnHack

    一.发现问题 先看两种方法插入数据 public void save(Person p){ SQLiteDatabase db = dbHelper.getWritableDatabase(); db ...

  4. jQuery $.extend()使用方法

    $.extend()使用方法总结. jQuery为开发插件提拱了两个方法,各自是: jQuery.fn.extend(object); jQuery.extend(object); jQuery.ex ...

  5. Oracle动态执行表不可访问解决方法

    在scott 用户下,执行查询语句是出现“Oracle动态执行表不可访问” 经查,是因为用户权限不够所致,修改scott用户权限语句如下: grant select on V_$session to ...

  6. 每日英语:Mercedes Sheds Its 'Old' Design

    Daimler AG's flagship Mercedes-Benz often gets the rap for being an 'old man's car.' More unusual is ...

  7. 每日英语:China Overtakes U.S. in Number of Diabetes Cases

    China is now home to the world's largest diabetes population. The number of people who have diabetes ...

  8. SpringCloud | FeignClient和Ribbon重试机制区别与联系

    在spring cloud体系项目中,引入的重试机制保证了高可用的同时,也会带来一些其它的问题,如幂等操作或一些没必要的重试. 今天就来分别分析一下 FeignClient 和 Ribbon 重试机制 ...

  9. Mixing ASP.NET Webforms and ASP.NET MVC

    https://www.packtpub.com/books/content/mixing-aspnet-webforms-and-aspnet-mvc *********************** ...

  10. js 时间格式与时间戳的相互转换和计算几天后的日期是哪一天

    //把日期转换成时间戳 function get_unix_time(time1){    var newstr = time1.replace(/-/g,'/');     var date =  ...