数据结构与算法--二叉树实现原理

二叉树

  • 二叉树(binary tree)是一棵树,其中每个节点都不能有多于两个的子节点
  • 二叉树的一个性质是一颗平均二叉树的深度要比节点个数N小得多(重点),对二叉树的分析得出其平均深度为O(N\sqrt NN),而对于特殊类型的二叉树,即二叉查找树(binary search tree)其深度的平均值是O(logN)。不过极端情况如下案例,深度可以达到N-1;

在这里插入图片描述

实现
  • 因为一个二叉树节点最多有两个子节点,所有可以保存直接连接到他们的链。树节点的声明在结构上类似双向链表,在声明中,节点就是element的信息加上两个其他节点的引用(left和right)组成的结构。
/*** 二叉树节点对象定义** @author liaojiamin* @Date:Created in 15:24 2020/12/11*/
public class BinaryNode {private Object element;private BinaryNode left;private BinaryNode right;public BinaryNode(Object element, BinaryNode left, BinaryNode right) {this.element = element;this.left = left;this.right = right;}public Object getElement() {return element;}public void setElement(Object element) {this.element = element;}public BinaryNode getLeft() {return left;}public void setLeft(BinaryNode left) {this.left = left;}public BinaryNode getRight() {return right;}public void setRight(BinaryNode right) {this.right = right;}
}
  • 我们习惯在画链表的时候,使用矩形标识,当我们表达树的时候用圆圈,并用直线连接,因为他实际上是图(graph)。当涉及树的时候,我们也不明显的画出null节点,因为具有N个节点的每一个二叉树都需要N+1个null节点。
  • 二叉树有许多与搜索无关的引用,主要的是编译器的设计领域。
案例:表达式树
  • 图中线上一个表达式树(expression tree)的案例,表达式树的叶子是操作数,如常数或者变量名,而其他的节点是操作符。由于所有操作符都是二元的(+,-,,/),因此这棵树正好可以被二叉树标识,虽然这是最简单情况,当还是可以有可能含有多于两个的子节点。一个节点也有可能只有一个儿子,如具有一目减运算符的情形。我们将通过递归计算左子树和右子树所得到的的值应用在根处的运算符而计算出表达式书T的值。在本案例中,左子树的值是无需计算,只有一个节点1, 右子树的值(23-4)+5,因此整个表达式是1+2*3-4+5
  • 我们通过递归经过左节点,中节点,右节点的顺序打印表达式,这种遍历方式叫中序遍历
  • 另外一种遍历策略,递归打印左节点,右节点,中节点,输出为:123*4-5++,这种输出策略称为后顺遍历
  • 第三种遍历策略是先打印运算符**(中节点),然后递归打印左子树右子树**,得到的结果:+1±*2345 ,这种遍历方式叫前序遍历
  • 在这里插入图片描述
构造表达式树
  • 我们先给出一种算法将后缀表达式转表达式树。我们已经有了将中缀表达式转后缀表达式的算法(见上一篇),因此我们能够从这两常见类型的输入生成表达式树。这里所描述的方法和后缀求职算法相似(上一篇),流程如下:
    • 我们遍历表达式,如果是符合操作数(数字),就建立一个单节点树并推入栈
    • 如果没有符合是操作符(运算符),那么将栈中弹出两个树T1,T2,(T1先出栈)
    • 将运算符,T1,T2 组成一个新的数,改树根节点是操作符,右节点是T1, 左节点是T2,
    • 将新数重新压入栈
  • 还是按上面的案例(1 2 3 * 4 - 5 + +)
  • 动图展示整个数构造过程
    在这里插入图片描述
代码实现
/*** 后缀表达式 转表达式树** @author liaojiamin* @Date:Created in 15:25 2020/12/11*/
public class PostfixExTOTreeEx {public static BinaryNode toTreeEx(String postfixEx) {MyStack<Object> number = new MyStack<>();String[] chars = postfixEx.split(" ");for (String s : chars) {if (s.matches("([1-9]\\d*\\.?\\d*)|(0\\.\\d*[1-9])")) {//数字number.push(s);}else if (s.matches("(\\*)|(\\/)|(\\+)|(\\-)")) {if (number.size() < 2) {return null;}BinaryNode binaryRight = null;Object right = number.pop();if(right instanceof BinaryNode){binaryRight = (BinaryNode) right;}else {binaryRight = new BinaryNode(right, null, null);}BinaryNode binaryLeft = null;Object left = number.pop();if(left instanceof BinaryNode){binaryLeft = (BinaryNode) left;}else {binaryLeft = new BinaryNode(left, null, null);}number.push(new BinaryNode(s, binaryLeft, binaryRight));}}return (BinaryNode) number.pop();}/*** 中序遍历* @author: liaojiamin* @date: 18:15 2020/12/11*/public static void printMiddleFirstTree(BinaryNode binaryNode){if(binaryNode == null || binaryNode.getElement() == null){return;}printMiddleFirstTree(binaryNode.getLeft());System.out.print(binaryNode.getElement());printMiddleFirstTree(binaryNode.getRight());}/*** 前序遍历* @author: liaojiamin* @date: 18:15 2020/12/11*/public static void printLeftFirstTree(BinaryNode binaryNode){if(binaryNode == null || binaryNode.getElement() == null){return;}System.out.print(binaryNode.getElement());printLeftFirstTree(binaryNode.getLeft());printLeftFirstTree(binaryNode.getRight());}/*** 后序遍历* @author: liaojiamin* @date: 18:15 2020/12/11*/public static void printRightFirstTree(BinaryNode binaryNode){if(binaryNode == null || binaryNode.getElement() == null){return;}printRightFirstTree(binaryNode.getLeft());printRightFirstTree(binaryNode.getRight());System.out.print(binaryNode.getElement());}public static void main(String[] args) {BinaryNode binaryNode = toTreeEx("1 2 3 * 4 - 5 + +");printMiddleFirstTree(binaryNode);System.out.println();printLeftFirstTree(binaryNode);System.out.println();printRightFirstTree(binaryNode);}}

上一篇:数据结构与算法–链表实现以及应用
下一篇:数据结构与算法–重建二叉树

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

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

相关文章

[C++STL]C++实现stack容器适配器

代码如下: #include <iostream> #include <deque> using namespace std;template<typename T,typename Con deque<T>> class Stack { public:Stack() {}void Push(const T &x) {_c.push_back(x);}void Pop(){_c.pop_back();}T & Top(){retur…

Istio Pilot架构解析

本文节选自 ServiceMesher 社区联合编写的《Istio Handbook——Istio 服务网格进阶实战》。本书地址&#xff1a;https://github.com/servicemesher/istio-handbook/在应用从单体架构向微服务架构演进的过程中&#xff0c;微服务之间的服务发现、负载均衡、熔断、限流等服务治理…

数据结构与算法--二叉查找树实现原理

二叉查找树 二叉树的一个重要应用就是他在查询中的使用&#xff0c;假设书中每个节点存储一项数据。在我们的案例中&#xff0c;任意复杂的项在java中都容易处理&#xff0c;但为了简单还是假设都是整数。还假设他们都是不重复的整数&#xff0c;使二叉树称为二叉查找树的性质…

[C++STL]C++实现queue容器适配器

代码如下: #include <iostream> #include <deque>using namespace std;template<typename T,typename Con deque<T>> class Queue { public:Queue(){}void Push(const T & x){_c.push_back(x);}void Pop(){_c.pop_front();}T &Back(){return…

当模板方法遇到了委托函数,你的代码又可以精简了

现如今当你翻看一些开源项目源码的时候&#xff0c;你会发现现在到处充斥着委托函数&#xff0c;如Func,Action,Predicate&#xff0c;确实现在的C#在函数式编程 的路上越来越成为主流&#xff0c;越来越显示威力&#xff0c;曾经的一些经典设计模式写法&#xff0c;在函数式下…

数据结构与算法--面试必问AVL树原理及实现

数据结构与算法–AVL树原理及实现 AVL&#xff08;Adelson-Velskii 和landis&#xff09;树是带有平衡条件的二叉查找树&#xff0c;这个平衡条件必须容易实现&#xff0c;并且保证树的深度必须是O(logN)。因此我们让一棵AVL树中每个节点的左子树和右子树的高度最多相差1&…

MySQL8.0新特性

在这之前Mysql的版本是5.7&#xff0c;也是目前使用最广泛的一个版本。现在新版本跳过了6和7直接来到了8&#xff0c;那么V6和V7版本去哪里了呢&#xff1f;比较靠谱的说法是v6用作了内部的其他用途而v7的话是因为mysql有个产品叫做clusterdb他有7这个版本&#xff0c;所以这个…

数据结构与算法--B树原理及实现

B树 前几篇文中讨论的数据结构我们都是假设所有的数据都存储在计算机的主存中。可说总要那么海量的数据需要通过个中数据结构去存储&#xff0c;我们不可能有这么多内存区存放这些数据。那么意味着我们需要将他们放磁盘。所以这个时候范问时间复杂度O决定了他是否能适合存储磁盘…

[C++STL]C++实现priority_queue容器适配器

代码如下: #pragma once #include <iostream> #include <vector> using namespace std;template<typename T> struct Less {bool operator()(const T &a, const T &b){return a < b;} };template<typename T> struct Greater {bool operat…

为什么要用内插字符串代替string.format

知道为什么要用内插字符串&#xff0c;只有踩过坑的人才能明白&#xff0c;如果你曾今使用string.format超5个以上占位符&#xff0c;那其中的痛苦我想你肯定是能够共鸣的。一&#xff1a;痛苦经历先上一段曾今写过的一段代码&#xff0c;大家来体会一下&#xff1a;LogHelper.…

SpringCloud Alibaba 框架下公司架构图

上一篇&#xff1a;Docker容器实战思维 下一篇&#xff1a;分布式事务理论模型

C++ 实现堆

代码如下(小根堆): #include <iostream> #include <assert.h> using namespace std;//小根堆,堆排序从大到小排 class Heap { public:Heap():data(nullptr), size(0), capacity(0) {}~Heap(){delete[] data;data nullptr;size 0;capacity 0;}/*void Swap(int *…

iPhone上运行Linux也要来了

FOSSBRTES 报道称&#xff0c;用户很快将可以通过双启动功能&#xff0c;像在 Android 设备上那样在 iPhone 上运行 Linux。目前&#xff0c;iOS 越狱极客、开发人员 Raffaele 以及 mcg29 已在其 Github 页面上发布了详细说明&#xff0c;详细介绍了如何双启动 64 位 iOS 设备。…

数据结构与算法--图论,最短路算法,拓扑排序算法

图论若干定义 图&#xff08;graph&#xff09;G&#xff08;V,E&#xff09;由定点vertex的集合V&#xff0c; 和边edge的集合E组成。每一条边都是一个点对点&#xff08;v&#xff0c;w&#xff09;&#xff0c;其中 v,w 属于V集合的子集 如果点对点 是有序的&#xff0c;那…

谁说.NET不适合搞大数据、机器学习和人工智能

SciSharp StackSciSharp STACK: https://scisharp.github.io/SciSharp/基于.NET的开源生态系统&#xff0c;用于数据科学、机器学习和AI。SciSharp将所有主要的ML/AI框架从Python引入.NET.特点为.NET开发者.NET开发者使用他们所了解和喜爱的工具可以最高效的工作。我们的使命是…

C++ 泛型编程 实现红黑树RBTree

代码如下: #include <iostream> #include <ctime> using namespace std;enum COLOR {BLACK,RED };template<typename T> struct RBTreeNode {RBTreeNode<T> * _parent;RBTreeNode<T> * _left;RBTreeNode<T> * _right;T _val;COLOR _color…

数据结构与算法--图论-深度优先搜索及其应用

深度优先搜索 深度优先搜索&#xff08;depth-first search&#xff09; 是对先序遍历&#xff08;preorder traversal&#xff09;的推广&#xff0c;我们从某个顶点v开始处理v&#xff0c;然后递归的遍历所有与v邻接顶点。如果这个过程是对一棵树进行&#xff0c;那么&#…

.NET Core技术研究-主机

前一段时间&#xff0c;和大家分享了 ASP.NET Core技术研究-探秘Host主机启动过程但是没有深入说明主机的设计。今天整理了一下主机的一些知识&#xff0c;结合先前的博文&#xff0c;完整地介绍一下.NET Core的主机的设计和构建启动过程。一、什么是主机主机是一个封装了应用资…

数据结构与算法--贪婪算法

贪婪算法 贪婪算法分阶段地工作。在每个阶段&#xff0c;可以认为所做决定是最好的&#xff0c;而不考虑将来的后果。通常这意味着选择的是某个局部最优。这种“当前能获得的最优就拿”的策略是这类算法的名字来源。当算法终止时候&#xff0c;我们希望的到累积的局部最优解就…

[C++STL]C++ 实现map容器和set容器

代码如下: #pragma once #include <iostream> using namespace std;enum COLOR {BLACK, RED };template<class V>//迭代器声明&#xff0c;定义在后面 struct RBTreeIterator;template<typename V> struct RBTreeNode {RBTreeNode<V> * _parent;RBTre…