春招来了,辞了职在家里准备再找份实习工作。相信大家,尤其是大三、大四的同学都经常在招聘要求上看到这样一条要求:熟悉常见的数据结构与算法。常见的数据结构通常有:链表二叉树,如果要求再高点,可能会让你实现红黑树AVL树这种高级的数据结构。由此可见,数据结构与算法还是比较重要的,最近也是在复习这方面的知识。本篇为复习过程中遇到过的总结,同时也给各位跟我一样准备面试的同学一份参考。另外,由于篇幅有限,本篇的重点在于二叉树的常见算法以及实现。

常见的二叉树实现代码

之前写过相关的文章,是关于如何创建及遍历二叉树的,这里不再赘述。提供链接给各位感兴趣的小伙伴,点此跳转

翻转二叉树

对于一棵二叉树,翻转它的左右子树,如下图所示:

下面来分析具体的实现思路:

  • 对于根结点为空的情况
    这种情况需要排除,因为null不是一个对象,不可能存在左右子树并且可以翻转的情况
  • 对于一棵只有一个根结点的二叉树
    emmm,这种情况也可以翻转,因为此时根结点左右子树为null,交换左右子树其实也就是在交换两个null,理论上是翻转了,但实际上我们看到的和没有翻转之前的结果是一样的
  • 对于一棵具有两个或两个以上结点的二叉树,此时二叉树可以表示为如下的图像:

可以看出,无论是只有左子树还是只有右子树都可以进行翻转。这句话等价于,为空的子树可以和不为空的子树进行交换,也就是不对为空的子树进行特殊处理

分析过程

其实这样我们还是不知道二叉树是如何翻转的,我们可以用第一张图的二叉树为例子,看一下翻转的具体过程。

  1. 首先我们需要对根结点进行判空处理,在根结点不为空的情况下存在左右子树(即使左右子树为空),然后交换左右子树;

2. 把根结点的左子树当成左子树的根结点,对当前根结点进行判空处理,不为空时交换左右子树; 3. 把根结的右子树当成右子树的根结点,对当前根结点进行判空处理,不为空时交换左右子树;4. 重复步骤23,最后二叉树变为原来的镜像结构,结果可以参考文章第一张示意图。

示例代码

根据上面的推理过程我们可以得出如下的代码:

function reverseTree(root){if( root !== null){[root.left, root.right] = [root.right, root.left]reverseTree(root.left)reverseTree(root.right)}
}
复制代码

虽然推理过程比较复杂(也可能是写的比较啰嗦。。),但是仔细观察代码,这和遍历的代码似乎也没多大差别,只是把输出结点变为了交换结点。

判断二叉树是否完全对称

一棵左右完全对称的二叉树是这样的:

那到底如何判断呢?

  • 根结点为空时,此时为一棵空二叉树,满足对称条件(-_-||)
  • 只有一个根结点时,左右子树都为null,满足左右对称条件
  • 只有两个结点时,此时左右子树必定有一个为空,不可能存在对称的情况
  • 结点数在三个及三个以上时,二叉树有对称的可能。

按照我们正常的思维,看对称与否,首先看左边,然后看右边,最后比较左右是否相等。同时我们注意到,在二叉树深度比较大的时候,我们光是比较左右是不够的。可以观察到,我们比较完左右以后还需要比较左的左右的右,比较左的右右的左

分析过程

这么看是比较绕,接下来我们来看图分析:

  1. 先比较根结点左右孩子
  2. 左子树根结点的左孩子右子树根结点的右孩子进行比较
  3. 左子树根结点的右孩子右子树根结点的左孩子进行比较
  4. 重复以上过程...

示例代码

function isSymmetrical(pRoot)
{// write code hereif(!pRoot){return true}return funC(pRoot.left, pRoot.right)
}function funC(left, right){if(!left){return right === null}if(!right){return false}if(left.val !== right.val){return false}return funC(left.right, right.left) && funC(left.left, right.right)
}
复制代码

求二叉树的深度

分析过程

  • 只有一个根结点时,二叉树深度为1
  • 只有左子树时,二叉树深度为左子树深度加1
  • 只有右子树时,二叉树深度为右子树深度加1
  • 同时存在左右子树时,二叉树深度为左右子树中深度最大者加1

示例代码

function deep(root){if(!root){return 0}let left = deep(root.left)let right = deep(root.right)return left > right ? left + 1 : right + 1
}
复制代码

求二叉树的宽度

二叉树的宽度是啥?我把它理解为具有最多结点数的层中包含的结点数,比如下图所示的二叉树,其实它的宽度就是为4:

分析过程

根据上图,我们如何算出二叉树的宽度呢?其实有个很简单的思路:

  1. 算出第一层的结点数,保存
  2. 算出第二层的结点数,保存一二层中较大的结点数
  3. 重复以上过程

示例代码

根据分析过程,我们可以利用队列这种数据结构来实现这个算法,代码如下:

function width(root){if(!root){return 0}let queue = [root], max = 1, deep = 1while(queue.length){while(deep--){let temp = queue.shift()if(temp.left){queue.push(temp.left)}if(temp.right){queue.push(temp.right)}}deep = queue.lengthmax = max > deep ? max : deep}return max
}
复制代码

重建二叉树

常见的遍历

  • 前序遍历: 前序遍历首先访问根结点然后遍历左子树,最后遍历右子树

  • 中序遍历: 中序遍历首先访问左子树然后遍历根节点,最后遍历右子树

  • 后序遍历: 后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点

题目描述

根据前序遍历产生的序列和中序遍历产生的序列生成一颗二叉树

思路分析

假如有这么一棵二叉树:

可以看出它前序遍历序列为:8 6 5 7 10 9 11中序遍历序列为:5 6 7 8 9 10 11 其中有个很明显的特征,根结点的值为前序遍历序列的第一个值,而且我们在中序遍历序列中很容易看出,根结点左右两边的结点分别为构成左子树右子树的结点,所以我们可以得到一种解决问题的思路:

  1. 获取前序遍历的第一个值,构建根结点
  2. 生成左子树的前序遍历序列和中序遍历序列
  3. 生成右子树的前序遍历序列和中序遍历序列
  4. 重复以上过程...

示例代码

function reConstructBinaryTree(pre, vin)
{if(!pre || !vin || !pre.length || !vin.length){return null}let root = new TreeNode(pre[0]),tIndex = vin.indexOf(pre[0]),leftIn = [],leftPre = [],rightIn = [],rightPre = []for(let i = 0; i < tIndex; i++){leftIn.push(vin[i])leftPre.push(pre[i+1])}for(let i = tIndex+1; i < pre.length; i++){rightIn.push(vin[i])rightPre.push(pre[i])}//递归root.left = reConstructBinaryTree(leftPre, leftIn)root.right = reConstructBinaryTree(rightPre, rightIn)return root
}
复制代码

以上思路、代码有错漏请在评论区指出!

总结

代码部分来自牛客网--剑指offer,相应的题目也都可以在上面找到。不过在这期间,我也是找到了份实习工作,年后就要去搬砖了。既然找到了,春招就不参与了(春招难度比秋招难太多了)希望看这篇文章的同学们也能找到份合适的工作。

坐下,这些都是二叉树的基本操作!相关推荐

  1. 二叉树的基本操作及哈夫曼编码/译码系统的实现

    二叉树的基本操作及哈夫曼编码/译码系统的实现 实验目的和要求 掌握二叉树的二叉链表存储表示及遍历操作实现方法. 实现二叉树遍历运算的应用:求二叉树中叶结点个数.结点总数.二叉树的高度,交换二叉树的左右 ...

  2. 手写二叉树的基本操作

    本题题目来源是: https://pta.patest.cn/pta/test/1342/exam/3/question/20490 老实说,写二叉树的基本操作写的我心慌意乱,主要原因是总感觉递归学的 ...

  3. 实现二叉树的基本操作(Java版)

    近期研究了一下二叉树,试着用Java语言实现了二叉树的基本操作,下面分享一下实现代码: package com.sf.test;import java.util.ArrayDeque; import ...

  4. 二叉树的基本操作(c语言)

    二叉树的基本操作 创建二叉树 二叉树的叶子节点 二叉树的节点总数 二叉树的高度 二叉树的基本遍历方法 创建二叉树 代码: // 创建二叉树,使用# void createBiTree(BiTree&a ...

  5. 二叉树的基本操作之二叉排序树

    //二叉树的基本操作之-建立二叉排序树并遍历 #include<stdio.h> #include<string.h> struct Node{Node *lchild;Nod ...

  6. 树的基本操作代码 c语言,二叉树的基本操作(C语言、源代码)

    二叉树的基本操作(源代码) #include "stdio.h" #include "malloc.h" #define MAX 100 typedef str ...

  7. 二叉树的基本操作——数据结构实验报告

    一.实验名称:二叉树 二.实验目的 1)熟练掌握二叉树的存储方式的具体实现过程,实现二叉树的基本操作及运算: 2)进一步巩固指针的用法,栈及队列的基本操作,进一步体会递归算法,学会综合应用. 三.实验 ...

  8. 数据结构实验报告,二叉树的基本操作(C语言)

    数据结构实验报告,二叉树的基本操作(C语言) 作者:命运之光 专栏:数据结构 目录 数据结构实验报告,二叉树的基本操作(C语言) 实验六 二叉树的基本操作 一.需求分析 二.概要设计 三.详细设计 四 ...

  9. 数据结构实验 二叉树的基本操作

    数据结构实验 二叉树的基本操作 实验环境: Visual C++ 实验目的: 1.掌握二叉树的定义: 2.掌握二叉树的基本操作,如二叉树的建立.遍历.结点个数统计.树的深 度计算等. 实验内容: 用递 ...

最新文章

  1. Android SDK Manager无法下载包的问题
  2. python中文分词jieba总结
  3. Spring里Bean类的运行时小写之谜
  4. 转-《高性能mysql》并不是一本好书——SQL笔记
  5. hdu3535 (分组背包,最少选一 + 最多选一 + 随意)
  6. cpu超频软件_Easy OC,装机小白进阶大神的好用软件
  7. 推荐系统组队学习——矩阵分解和FM
  8. java使用jeids实现redis2.6的HyperLogLog数据结构的操作
  9. 【ACL2020】今日放榜,779篇论文被接收,姚班校友陈丹琦首日演讲
  10. opencv的下载报错解决
  11. 推动5G+北斗高精度定位系统更好赋能千行百业
  12. 房产中介管理系统软件的开发和使用(附源码)
  13. 纯屏和液晶显示器有什么区别
  14. Robocup3D优化任务布置
  15. 听说,年终总结写不好,绩效要被打 C
  16. gis 六边形网格_六边形网格快速定位
  17. 三维人脸_无法打开gl\glaux.h头文件及无法生成 SAFESEH 映像的解决方法
  18. Vue3 中如何加载动态菜单?
  19. win10下启动.bat文件闪退问题
  20. 对转义字符“\”的理解

热门文章

  1. idea如何彻底删除一个项目
  2. php 导出csv文件
  3. 正则表达式元字符整理
  4. django中,kindeditor存到数据库的html,前台html标签被自动转义的解决办法
  5. Spread for Windows Forms快速入门(1)---开始使用Spread
  6. AIX 添加开机启动项
  7. AndroidManifest详解
  8. Silverlight3系列(一)Silverlight配合WCF进行数据库操作
  9. 关于Spring中IOC容器和AOP协同工作的原理理解
  10. jupyter安装出现问题:安装后无法打开