二叉查找树

【0】README

0.1)本文的重点在于介绍 二叉查找树的概念,以及写出 二叉查找树的操作例程的源代码, 其中当属delete 操作的源代码最不容易实现;
0.2)本文源代码均为原创, 当然 代码中的idea 是借鉴人家的;


【1】二叉查找树相关概念

1.1)定义:该树中的每个节点 X, 它的左子树中所有关键字值 小于 X 的关键字值, 而它的右子树中所有关键字值大于 X 的关键字值;
这里写图片描述
1.2)性质: 二叉查找树的平均深度是 O(log N);
1.3)编写对二叉树的操作:由于树的递归定义,通常是递归地编写这些操作的例程;


【2】 二叉查找树的操作例程(我们只选取了 find 和 delete 进行 解析)

2.1)Find

  • Attention) 要知道, 不管是 find 二叉树还是 find 二叉查找树, 它的第一条执行语句一定是判断根节点 是否 为 NULL;(也即是P75 提到的, 对空树的测试放在最前面)
  • Find函数的关键问题是: 首先要对是否为空树进行测试, 否则就可能在 NULL 指针上面兜圈子;

2.2) Delete
一旦发现要被删除的节点, 要考虑以下几种情况:

  • case1)如果节点是一片树叶,那么它可以被立即删除;
  • case2)如果节点有一个儿子, 则该节点可以在其父节点调整指针绕过该节点后被删除;
  • case3)复杂的情况是处理具有两个儿子的节点。一般的删除策略是用其右子树的最小的数据代替该节点的数据并递归地删除那个节点(现在它是空的)。因为右子树中的最小节点不可能有 左儿子, 所以第二次 Delete(删除) 要容易;
    这里写图片描述
  • 引入懒惰删除(我的源代码中没有采用懒惰删除,这里旨在了解懒惰删除的概念):当一个元素要被删除时, 它仍留在树中, 而是只做了一个被删除的标记而已;
    • 懒惰删除优点: 1.如果被删除的关键字是重新插入的, 那么分配一个新单元的开销就避免了;

2.3)关于二叉查找树的所有操作实例的源代码 + 测试结果:

1 ) download source code : https://github.com/pacosonTang/dataStructure-algorithmAnalysis/blob/master/chapter4/p74_binary_search_tree.c

2 ) source code at a glance :

#include <stdio.h>
#include <malloc.h>#define ElementType int
#define Error(str) printf("\n error: %s \n",str)   struct BinarySearchTree;
typedef struct BinarySearchTree *BinarySearchTree;BinarySearchTree createBinarySearchTree(ElementType);
BinarySearchTree makeEmpty(BinarySearchTree);
BinarySearchTree insert(ElementType, BinarySearchTree) ;
BinarySearchTree deleteBinarySearchTree(ElementType, BinarySearchTree);// we adopt child-sibling notation
struct BinarySearchTree
{ElementType value;BinarySearchTree left;BinarySearchTree right;
};// create a BinarySearchTree with root node
BinarySearchTree createBinarySearchTree(ElementType value)
{   BinarySearchTree t;t = (BinarySearchTree)malloc(sizeof(struct BinarySearchTree));if(!t) {Error("out of space, from func createBinarySearchTree");        return NULL;}    t->left = NULL;t->right = NULL;    t->value = value;return t;
}// make the BinarySearchTree empty 
BinarySearchTree makeEmpty(BinarySearchTree t)
{if(t){makeEmpty(t->left);makeEmpty(t->right);        free(t);}           return NULL;
}BinarySearchTree insert(ElementType e, BinarySearchTree root) 
{           if(!root) {// find the node with its left or right being NULLroot = createBinarySearchTree(e);if(root)return root;else return NULL;}if(e > root->value)  // the tree node with value e inserting into right child of the parent root->right = insert(e, root->right);    else if(e < root->value)  // the tree node withe value e inserting into left child of the parent        root->left = insert(e, root->left); elseError(" you cannot insert the node into the tree for its value equals to one in the tree");return root; // dont't forget this line !
}// find the BinarySearchTree root node with value equaling to e
//Attention: the first statement must judge whether root is NULL or not
BinarySearchTree find(ElementType e, BinarySearchTree root)
{       if(!root) // judge whether root is NULL or notreturn NULL;if(e > root->value)return find(e, root->left); else if(e < root->value)return find(e, root->left);else return root;
} // find the minimum, (Attention for its non-recursion implementation )
BinarySearchTree findMin(BinarySearchTree root)
{if(root) {if(root->left)return findMin(root->left);elsereturn root;}    return NULL;
}// find the Maximum, (Attention for its non-recursion implementation )
BinarySearchTree findMax(BinarySearchTree root)
{if(root) {if(root->right)return findMax(root->right);elsereturn root;}    return NULL;
}// delete the node with given value e from the binary search tree
BinarySearchTree deleteBinarySearchTree(ElementType e, BinarySearchTree root)
{BinarySearchTree temp;if(!root)Error(" elements not found, from func deleteBinarySearchTree ");if(e > root->value) root->right = deleteBinarySearchTree(e, root->right);else if(e < root->value) root->left = deleteBinarySearchTree(e, root->left);else {// the value of root equals given eif(root->left && root->right) { // if the deleting node has both left and rightroot->value = findMin(root->right)->value; // set root's value the minimum of right tree of rootroot->right = deleteBinarySearchTree(root->value, root->right);         }       else { // one or zero child is not NULL// root->left = deleteBinarySearchTree(root->value, root->left);                        if(root->right) { // if root->right doesn't equal to NULLtemp = root;root = root->right;free(temp);                                             }else if(root->left){ // if root->left doesn't equal to NULLtemp = root;root = root->left;free(temp);             }else { // if both root->left and root->right equal to NULLfree(root);root = NULL;}}/* you can also fabricate code like this, which is reshipped from data_structure booktemp = root;if(!root->right)root = root->left;else if(!root->left)root = root->right;free(temp);*/}   return root;
}// analog print directories and files name in the BinarySearchTree, which involves postorder traversal. 
void printPreorder(int depth, BinarySearchTree root)
{           int i;if(root) {      for(i = 0; i < depth; i++)printf("    ");     printf("%d\n", root->value);printPreorder(depth + 1, root->left);                                           printPreorder(depth + 1, root->right); // Attention: there's difference between traversing binary tree and common tree                          }else {for(i = 0; i < depth; i++)printf("    ");     printf("NULL\n");}
}int main()
{BinarySearchTree bst;   int value[] = {2, 8, 1, 5, 3, 4};int i;printf("\n ====== test for preordering the BinarySearchTree ====== \n");        printf("\n test for creating a binary search tree with root value 6 \n");   bst = createBinarySearchTree(6);printPreorder(1, bst); printf("\n test for insertint 6 nodes, that's  2, 8, 1, 5, 3 and 4 in turn \n");        for(i = 0; i < 6; i++)insert(value[i], bst);      printPreorder(1, bst);       printf("\n test for find minimum \n");      printf(" the minimum is %2d, in this binary search tree! \n", findMin(bst)->value);printf("\n test for find maximum \n");      printf(" the maximum is %2d, in this binary search tree! \n", findMax(bst)->value);printf("\n test for deleting node '2' with two nodes from the binary search tree \n");      deleteBinarySearchTree(2, bst);printPreorder(1, bst);       printf("\n test for deleting node '5' with one node from the binary search tree \n");       deleteBinarySearchTree(5, bst);printPreorder(1, bst);       printf("\n test for deleting node '8' with zeron node from the binary search tree \n");     deleteBinarySearchTree(8, bst);printPreorder(1, bst);       printf("\n test for inserting '8', '5' and '2' into the binary search tree \n");        insert(8, bst);insert(5, bst);insert(2, bst);printPreorder(1, bst);       return 0;
}

这里写图片描述
这里写图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/332019.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常用的命名规范/命名规则

文章目录骆驼式命名法&#xff08;CamelCase&#xff09;帕斯卡命名法&#xff08;PascalCase&#xff09;串式命名法&#xff08;KebabCase&#xff09;下划线命名法&#xff08;UnderScoreCase&#xff09;骆驼式命名法&#xff08;CamelCase&#xff09; 也叫小驼峰式命名法…

spring order_Spring @Order批注

spring order介绍&#xff1a; Spring Order注释是在Spring 2.0中首次引入的。 然后&#xff0c;它仅用于定义AspectJ建议中的顺序。 在Spring 4.0的后面&#xff0c;对该注释的实现进行了进一步改进。 从那时起&#xff0c;它还支持对Java数组或List之类的集合中的Spring组件或…

AVL树

【0】README 0.1&#xff09;本文给出了平衡二叉树&#xff08;AVL树&#xff09;的插入例程涉及到的单旋转双旋转的概念&#xff0c;并给出了代码实现&#xff1b; 0.2&#xff09;本文源代码均为原创&#xff0c; 当然相关idea 还是借鉴人家的&#xff1b;&#xff08;真心…

spring 注释_Spring@懒惰注释

spring 注释介绍&#xff1a; 默认情况下&#xff0c; Spring框架在应用程序启动时加载并热切初始化所有bean。 在我们的应用程序中&#xff0c;我们可能有一些非常消耗资源的bean。 我们宁愿根据需要加载此类bean。 我们可以使用Spring Lazy批注实现此目的 。 在本教程中&…

管理系统的账户设计(涉及注册/登录逻辑)

文章目录方案一方案二方案三方案一 类似华为云IAM&#xff08;Identity and Access Management 身份和访问管理&#xff09;用户&#xff0c;阿里云的 RAM&#xff08;Resource Access Management 资源访问管理&#xff09;用户 机构有独立的账户&#xff08;主账户&#xff…

opencv生成日志_OpenCV-Utils学习日志:VideoCapture使用样例

1.VideoCapture可以打开多种来源的数据流&#xff0c;但常见的是相机、视频及图像序列三类数据流&#xff1a;(1)打开相机数据流&#xff0c;需要指定相机在主机上的设备编号&#xff0c;若主机上只有一个相机则编号通常是0。(2)打开视频数据流&#xff0c;需要指定视频的完整路…

jdbc查询序列_JDBC –模拟序列

jdbc查询序列也许我们每个人在程序员的生活中至少遇到过一次这个问题- 如何模拟数据库序列&#xff1f; 在下面&#xff0c;您可能会发现我对该问题解决方案的各种了解。 假设我们有一个接口定义了所需的API&#xff0c;用于返回整数序列&#xff1a; public interface Sequen…

利用 GregorianCalendar 制作当前月的月历

【0】README 0.1&#xff09;本文文字总结于 core java volume 1 &#xff0c; 源代码均为原创&#xff1b; 0.2&#xff09;本文旨在熟悉 GregorianCalendar 日历类&#xff0c;每一天就是一个GregorianCalendar 日历类&#xff0c;一天有很多的日历属性&#xff0c;觉得用它…

pyecharts怎么绘制散点图_PyeCharts绘制各种图形

简介PyeCharts 是一个用于生成 Echarts 图表的类库&#xff0c;用其生成的图可视化效果非常棒&#xff0c;而且使用起来非常简单。下面是一些常用图的pyecharts实现方法柱状图bar pye.Bar("柱状图")#新建柱状图bar.add("服装", #图例名称["衬衫"…

junit junit_穿越JUnit流

junit junit关于JUnit 5迁移的好处之一是&#xff0c;您可以在老式模式下运行JUnit 4测试&#xff0c;并且所有内容仍然兼容。 不利的一面是&#xff0c;某些注释和方法在JUnit 4和JUnit 5中具有相同的名称&#xff0c;并且当两组库依赖项都可用时&#xff0c;很容易导入错误的…

被遗忘的软件产品形态

从2010年以后&#xff0c;很多公司开发的软件产品&#xff0c;很少有客户端了&#xff0c;web2.0之后&#xff0c;主流的业务系统基本上都是基于Web去构建业务系统。这几年见到的业务应用系统都是基于Web的构建的。而在To C市场&#xff0c;几乎就没有客户端了&#xff0c;都是…

vue进行判断使用class_vue判断dom的class

vue点击给dom添加class然后获取含有class的dom{{item.name}}{{item2.name}}jschek(index2, index) {this.iac[index2] indexthis.iac this.iac.concat([]);this.checkchose()},checkchose:function(){var chosethisvar chosedomchose.$refs.choseboxconsole.log(chosedom)for…

方法参数的值调用+引用调用+深浅拷贝

【0】README 0.1&#xff09;本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理清值调用引用调用&#xff1b; 【1】参数传递给方法的专业术语&#xff1a; 1.1&#xff09;值调用&#xff1a;它表示方法接收的是调用者提供的值&#xff1b; 1.2&#xff09;引用…

设计模式 工厂方法_工厂方法设计模式

设计模式 工厂方法工厂方法模式是流行的创作设计模式之一。 它并不特别依赖于工厂对象来创建对象。 而是要在同一类中使用单独的方法来创建对象。 Factory Method模式定义了一个用于创建对象的接口&#xff0c;但是让子类决定如何实例化其对象。 每个子类必须定义其Factory方法…

靖江机器人怎么样_铁饭碗不保?靖江可能消失的12大职业!快看有你的工作没?...

原标题&#xff1a;铁饭碗不保&#xff1f;靖江可能消失的12大职业&#xff01;快看有你的工作没&#xff1f;无人飞机、无人驾驶、智能机器人....你能想象这些充满现代感的高科技正在改变我们的生活吗&#xff1f;在科技高速发展的今天人工智能逐渐能够代替人类的部分工作但&a…

MarkdownPad 汉化破解(含下载地址)

转自 http://jingyan.baidu.com/article/ca41422fe209271eaf99ed7c.html MarkdownPad是一个全功能Markdown编辑器的Windows。 【1】MarkdownPad 汉化破解&#xff08;含下载地址&#xff09; 工具/原料 MarkdownPad 2.4 方法/步骤 软件 下载地址&#xff08;本软件为绿色版…

捡对象引流脚本 内容_对象和索引流

捡对象引流脚本 内容我本来要写一篇关于如何将流与每个元素的索引混合的文章&#xff0c;但是Baeldung上的人们已经很好地涵盖了这个主题 &#xff01; 鉴于我是他们编辑团队的一员&#xff0c;我为他们/我们感到自豪。 有趣的是&#xff0c;特别是Streams中的Java函数式编程如…

散列之再散列

【0】README 0.1&#xff09;本文描述总结于 数据结构与算法分析&#xff0c; 但源代码为原创&#xff1b; 0.2&#xff09;为什么写这篇博文&#xff1f; 再散列的代码实现 包括了 解决冲突的方法实现&#xff1b;很有代表性&#xff1b;&#xff08;本源代码采用的解决冲突…

激活策略 查询_5个提问,详细介绍北极星指标的策略框架

北极星指标&#xff08;North Star Metric&#xff09;已经逐渐成为许多公司指导产品发展的重要指标&#xff0c;本文通过五个设问和多个行业案例&#xff0c;系统性地介绍北极星指标这类产品策略框架。如今有非常多的人在谈论和使用北极星指标&#xff08;North Star Metric&a…

变色龙嗅探卡功能_变色龙功能

变色龙嗅探卡功能在《神秘博士》中&#xff0c;卡梅利恩&#xff08;Kamelion&#xff09;角色是一个可以采取任何形式的机器人。 据称&#xff0c;他们使用的物理道具非常麻烦&#xff0c;只有其创建者才能理解&#xff0c;而该创建者并没有帮助纠正它。 因此&#xff0c;Cha…