Java进阶——数据结构与算法之哈希表与树的入门小结(四)

文章大纲

  • 引言
  • 一、哈希表
    • 1、哈希表概述
    • 2、哈希表的基本设计思想
    • 3、JDK中的哈希表的设计思想概述
  • 二、树
    • 1、树的概述
    • 2、树的特点
    • 3、树的相关术语
    • 4、树的存储结构
      • 4.1、双亲表示法
      • 4.2、孩子兄弟表示法:
      • 4.3、孩子表示法:
      • 4.4、双亲孩子表示法
  • 三、二叉树
    • 1、二叉树的性质
    • 3、二叉树的类型
    • 4、二叉树的存储结构
    • 5、二叉树的遍历
      • 5.1、先序遍历(根结点 ---> 左子树 ---> 右子树)
      • 5.2、中序遍历(左子树 ---> 根结点 ---> 右子树)
      • 5.3、后序遍历(左子树 ---> 右子树 ---> 根结点)
    • 6、二叉树的链式实现

引言

前面介绍了线性表结构中的顺序存储结构寻址容易但是插入删除性能不好,而链式结构插入删除性能较好寻址却欠佳,那么有没有“鱼和熊掌兼可得”的结构呢?

一、哈希表

1、哈希表概述

哈希表(Hash table也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。即它通过把关键码值映射到表中一个位置来访问记录,直接通过key来加快查找的速度,这个映射函数叫做散列函数,散列函数就是用于计算哈希值的,存放记录的数组叫做散列表

2、哈希表的基本设计思想

以一个实例简单分析下哈希表的设计思想,首先我们有一组数据{14,19,5,7,21,1,13,0,18}需要存储,暂且设计散列表长度为预存储数组的长度,最后再设计一个映射公式即散列函数表达式f(x)= x mod 13,经过映射之后无论多大的数据都能确保经过散列函数计算之后在散列表下标范围内(当然我们用的hashCode要比这复杂得多不过核心思想是一样的)
在这里插入图片描述
当然以上是一种简单的哈希表基本设计思想,适用于特定的场景,比如说通讯录、QQ好友列表、微信好友列表、字典等有上限的且重复不多的数据存储。

3、JDK中的哈希表的设计思想概述

JDK中采用的是所谓的拉链法,JDK1.7之前采用的是数组+单链表的结构,而在之后改成了数组+单链表+红黑树的结构,基本思想是一致的,区别在于解决哈希冲突的方案,JDK1.7之前散列表中存储的元素上一个单链表,当发生哈希冲突时,直接把值添加到链表尾部,这样就解决了哈希冲突,但是为了避免单链表长度过长,在JDK1.8之后设置来一个阈值,当链表长度超过这个阈值时则自动转为红黑树进行存储。
在这里插入图片描述

二、树

1、树的概述

树是一种数据结构,它是由n(n>=1)个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,不过它是根朝上,而叶朝下的,当n>0时根结点是唯一的,不可能存在多个根结点,数据结构中的树只能有一个根结点;.m>0时,子树的个数没有限制,但它们一定是互不相交的。单个结点是一棵树,树根就是该结点本身。

2、树的特点

  • 每个结点有零个或多个子结点
  • 没有父结点的结点称为根结点
  • 每一个非根结点有且只有一个父结点
  • 除了根结点外,每个子结点可以分为多个不相交的子树

3、树的相关术语

  • 结点的度——一个结点含有的子树的个数称为该结点的度;
  • 叶结点或终端结点——度为0的结点称为叶结点;
  • 非终端结点或分支结点——度不为0的结点;
  • 双亲结点或父结点——若一个结点含有子结点,则这个结点称为其子结点的父结点
  • 孩子结点或子结点——一个结点含有的子树的根结点称为该结点的子结点
  • 兄弟结点——具有相同父结点的结点互称为兄弟结点;
  • 树的度——一棵树中,最大的结点的度称为树的度;
  • 结点的层次——从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
  • 树的高度或深度——树中结点的最大层次
  • 堂兄弟结点——双亲在同一层的结点互为堂兄弟;
  • 结点的祖先——从根到该结点所经分支上的所有结点
  • 子孙——以某结点为根的子树中任一结点都称为该结点的子孙。
  • 森林——由m(m>=0)棵互不相交的树的集合称为森林;

在这里插入图片描述

4、树的存储结构

树的存储结构有有四种:双亲表示法孩子兄弟表示法孩子表示法双亲孩子表示法

4.1、双亲表示法

把所有节点都村存在一组连续空间中,同时在每个结点中,附设一个指示器指示其双亲结点到链表中的位置。
节点结构为

data(数据域)parent(指针域)
存储结点的数据信息存储该结点的双亲所在数组中的下标
在这里插入图片描述

根节点的指针域为-1,根据结点的parent指针很容易找到它的双亲结点。所用时间复杂度为O(1),直到parent为-1时,表示找到了树结点的根。

4.2、孩子兄弟表示法:

任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的右兄弟如果存在也是唯一的。因此我们设置两个指针,分别指向该结点的第一个孩子和此结点的右兄弟,结点结构:

data(数据域)firstchild(指针域)rightsib(指针域)
data是数据域存储该结点的第一个孩子结点的存储地址存储该结点的右兄弟结点的存储地址
在这里插入图片描述

4.3、孩子表示法:

把每个结点的孩子结点排列起来,以单链表作存储结构,则n个结点有n个孩子链表,如果是叶子结点则此单链表为空,然后n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中。为此设计两种结点结构:一种是孩子链表的孩子结点:

child(数据域)next(指针域)
存储某个结点在表头数组中的下标存储指向某结点的下一个孩子结点的指针
另一种是表头数组的表头结点:
data(数据域)firstchild(头指针域)
存储某个结点的数据信息存储该结点的孩子链表的头指针

在这里插入图片描述

4.4、双亲孩子表示法

在这里插入图片描述

三、二叉树

二叉树是**每个结点最多有两个子树的树结构,**通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树不是树的一种特殊情形,尽管其与树有许多相似之处,但树和二叉树有两个主要差别,树中结点的最大度数没有限制,而二叉树结点的最大度数为2, 树的结点无左、右之分,而二叉树的结点有左、右之分

1、二叉树的性质

  • 在非空二叉树中,第i层的结点总数不超过2的(i-1)次方 , i>=1
  • 深度为h的二叉树最多有 2的h次方减1个结点(h>=1),最少有h个结点
  • 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1
  • 具有n个结点的完全二叉树的深度为 [log2 N]+1 (注:[ ]表示向下取整)
  • 有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:若I为结点编号则 如果I>1,则其父结点的编号为I/2;如果2I<=N,则其左孩子(即左子树的根结点)的编号为2I;若2I>N,则无左孩子;如果2I+1<=N,则其右孩子的结点编号为2I+1;若2I+1>N,则无右孩子。
  • 给定N个节点,能构成h(N)种不同的二叉树。h(N)为卡特兰数的第N项。h(n)=C(2*n,n)/(n+1)。
  • 设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和J=I+2i [2]

3、二叉树的类型

  • 完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
  • 满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
  • 平衡二叉树——平衡二叉树又被称为AVL树(区别于AVL算法),它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

4、二叉树的存储结构

在这里插入图片描述

5、二叉树的遍历

遍历是对树的一种最基本的运算,所谓遍历二叉树就是按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次。由于二叉树是非线性结构,因此,树的遍历实质上是将二叉树的各个结点转换成为一个线性序列来表示。假设L、D、R分别表示遍历左子树、访问根结点和遍历右子树, 则对一棵二叉树的遍历有三种情况:DLR(称为先根次序遍历),LDR(称为中根次序遍历),LRD (称为后根次序遍历)。
在这里插入图片描述

5.1、先序遍历(根结点 —> 左子树 —> 右子树)

首先访问根,再先序遍历左子树,最后先序遍历右子树。

public void postOrderTraversal(TreeNode root) {if (root != null) {return;}postOrderTraversa1(root.left);postOrderTraversa1(root.right);System.out.print(root.val+"  ");
}

非递归版本

public void preOrderTraversval2(TreeNode root) {LinkedList<TreeNode> stack = new LinkedList<>();TreeNode pNode = root;while (pNode != null || !stack.isEmpty()) {if (pNode != null) {System.out.print(pNode.val+"  ");stack.push(pNode);pNode = pNode.left;} else { //pNode == null && !stack.isEmpty()TreeNode node = stack.pop();pNode = node.right;}}}

5.2、中序遍历(左子树 —> 根结点 —> 右子树)

首先中序遍历左子树,再访问根,最后中序遍历右子树

public void postOrderTraversal(TreeNode root) {if (root != null) {return;}postOrderTraversa1(root.left);postOrderTraversa1(root.right);System.out.print(root.val+"  ");
}

5.3、后序遍历(左子树 —> 右子树 —> 根结点)

首先后序遍历左子树,再后序遍历右子树,最后访问根,即

public void postOrderTraversal(TreeNode root) {if (root != null) {return;}postOrderTraversa1(root.left);postOrderTraversa1(root.right);System.out.print(root.val+"  ");
}

6、二叉树的链式实现

package com.crazymo.ndk.tree;public class BinaryTree<E> {public TreeNode<E> root;public BinaryTree(E data){root=new TreeNode<>(data,null,null);}public void createTree(){TreeNode<String> nodeB=new TreeNode<String>("B",null,null);TreeNode<String> nodeC=new TreeNode<String>("C",null,null);TreeNode<String> nodeD=new TreeNode<String>("D",null,null);TreeNode<String> nodeE=new TreeNode<String>("E",null,null);TreeNode<String> nodeF=new TreeNode<String>("F",null,null);TreeNode<String> nodeG=new TreeNode<String>("G",null,null);TreeNode<String> nodeH=new TreeNode<String>("H",null,null);TreeNode<String> nodeJ=new TreeNode<String>("J",null,null);TreeNode<String> nodeI=new TreeNode<String>("I",null,null);root.leftChild= (TreeNode<E>) nodeB;root.rightChild= (TreeNode<E>) nodeC;nodeB.leftChild=nodeD;nodeC.leftChild=nodeE;nodeC.rightChild=nodeF;nodeD.leftChild=nodeG;nodeD.rightChild=nodeH;nodeE.rightChild=nodeJ;nodeH.leftChild=nodeI;}/*** 中序访问树的所有节点*/public void midOrderTraverse(TreeNode<E> root){//逻辑if(root==null){return;}midOrderTraverse(root.leftChild);//逻辑System.out.print("mid:"+root.data+"\t");//输出midOrderTraverse(root.rightChild);//逻辑}/*** 前序访问树的所有节点  Arrays.sort();*/public void preOrderTraverse(TreeNode<E> root){if(root==null){return;}System.out.print("pre:"+root.data+"\t");preOrderTraverse(root.leftChild);preOrderTraverse(root.rightChild);}/*** 后序访问树的所有节点*/public void postOrderTraverse(TreeNode<E> root){if(root==null){return;}postOrderTraverse(root.leftChild);postOrderTraverse(root.rightChild);System.out.print("post:"+root.data+"\t");}/***节点的数据结构* @param <E>*/public class TreeNode<E> {E data;TreeNode<E> leftChild;TreeNode<E> rightChild;public TreeNode(E data, TreeNode<E> leftChild, TreeNode<E> rightChild) {this.data = data;this.leftChild = leftChild;this.rightChild = rightChild;}}
}

树的遍历

 BinaryTree binarayTree=new BinaryTree("A");//构造简单二叉树binarayTree.createTree();binarayTree.midOrderTraverse(binarayTree.root);System.out.println();binarayTree.preOrderTraverse(binarayTree.root);System.out.println();binarayTree.postOrderTraverse(binarayTree.root);

在这里插入图片描述在这里插入图片描述

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

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

相关文章

SAM在医学图像分割的一些研究(Segment Anything Model for Medical Images?(2023))

使用预训练模型通过两种主要模式进行分割&#xff0c;包括自动一切和手动提示(例如&#xff0c;点和框)。SAM在各种自然图像分割任务上取得了令人印象深刻的效果。然而&#xff0c;由于医学图像的形态复杂、解剖结构精细、物体边界不确定和复杂、物体尺度大&#xff0c;使得医学…

【第一阶段】kotlin的when表达式

1.Java 的if /when是语句 kotlin的if/when是表达式&#xff0c;表达式是有返回值的 java中void是个关键字&#xff0c;Unit在kotlin中是个类 2.当使用when语句的时候必须有一个不满足的值即else: fun main() {var week:Int5val info when(week){1->"今天是星期一"…

【iOS】—— UIKit相关问题

文章目录 UIKit常用的UIKit组件懒加载的优势 CALayer和UIView区别关系 UITableViewUITableView遵循的两个delegate以及必须实现的方法上述四个必须实现方法执行顺序其他方法的执行顺序&#xff1a; UICollectionView和UITableView的区别UICollectionViewFlowLayout和UICollecti…

em3288 linux_4.19 第一次烧写无法进入内核的情况

1. 情况一&#xff1a; /DDR Version 1.11 20210818 In SRX Channel a: DDR3 400MHz Bus Width32 Col10 Bank8 Row15 CS1 Die Bus-Width16 Size1024MB Channel b: DDR3 400MHz Bus Width32 Col10 Bank8 Row15 CS1 Die Bus-Width16 Size1024MB OUT Boot1 Release Time: Jul 22 2…

Jenkins插件管理切换国内源地址

一、替换国内插件下载地址 选择系统管理–>插件管理–> Available Plugins 并等待页面完全加载完成、这样做是为了把jenkins官方的插件列表下载到本地、接着修改地址文件、替换为国内插件地址 进入插件文件目录 cd /var/lib/jenkins/updatesdefault.json 为插件源地址…

STM32 LWIP UDP 一对一 一对多发送

STM32 LWIP UDP通信 前言设置 IP 地址UDP函数配置实验结果单播发送&#xff0c;一对一发送广播发送&#xff0c;一对多发送 可能遇到的问题总结 前言 之前没有接触过网络的通信&#xff0c;工作需要 UDP 接收和发送通信&#xff0c;在网上没有找到一对一、一对多的相关例程&am…

正则表达式在格式校验中的应用以及包装类的重要性

文章目录 正则表达式&#xff1a;做格式校验包装类&#xff1a;在基本数据类型与引用数据类型间的桥梁总结 在现代IT技术岗位的面试中&#xff0c;掌握正则表达式的应用以及理解包装类的重要性是非常有益的。这篇博客将围绕这两个主题展开&#xff0c;帮助读者更好地面对面试挑…

IIC子系统-实现si7006温湿度传感器采集温湿度功能

1.将IIC核心层和总线驱动层配置进内核 *********************配置核心层*************************1.找到核心层代码目录&#xff1a;内核顶层目录/drivers/i2c2. 内核顶层目录执行make menuconfig3. > Device Drivers > I2C support ->-*-I2C support4.保存退出***…

数据预处理matlab

matlab数据的获取、预处理、统计、可视化、降维 数据的预处理 - MATLAB & Simulink - MathWorks 中国https://ww2.mathworks.cn/help/matlab/preprocessing-data.html 一、数据的获取 1.1 从Excel中获取 使用readtable() 例1&#xff1a; 使用spreadsheetImportOption…

端口映射教程vs快解析内网穿透

随着社会信息化的发展&#xff0c;很多人都开始关注网络问题&#xff0c;掌握一些基础的网络知识是非常有必要的。其中&#xff0c;端口映射作为一项重要的技术&#xff0c;在网络通信中起到了至关重要的作用。 端口映射在现实生活中有着广泛的应用。如果你是一位游戏爱好者&a…

极狐GitLab 全新「价值流仪表盘」使用指南

本文来源&#xff1a;about.gitlab.com 作者&#xff1a;Haim Snir 译者&#xff1a;极狐(GitLab) 市场部内容团队 GitLab / 极狐GitLab 价值流仪表盘的使用相对简单&#xff0c;这种可以定制化的仪表盘能够让决策者识别数字化转型进程中的趋势及机遇。 如果你已经在用 GitLab…

NGZORRO:动态表单/模型驱动 的相关问题

官网的demo的[nzFor]"control.controlInstance"&#xff0c;似乎是靠[formControlName]"control.controlInstance"来关联的。 <form nz-form [formGroup]"validateForm" (ngSubmit)"submitForm()"><nz-form-item *ngFor&quo…

day50-Insect Catch Game(捉虫游戏)

50 天学习 50 个项目 - HTMLCSS and JavaScript day50-Insect Catch Game&#xff08;捉虫游戏&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport"…

【MySQL】数据库基本使用

文章目录 一、数据库介绍二、数据库使用2.1 登录MySQL2.2 基本使用2.2.1 显示当前 MySQL 实例中所有的数据库列表2.2.2 创建数据库2.2.3 创建数据库表2.2.4 在表中插入数据2.2.5 在表中查询数据 三、服务器、数据库、表之间的关系四、SQL语句分类五、存储引擎 一、数据库介绍 …

图卷积网络(GCN)和池化

一、说明 GCN&#xff08;Graph Convolutional Network&#xff09;是一种用于图形数据处理和机器学习的神经网络架构。GCN 可以在图形中捕获节点之间的关系&#xff0c;从而能够更好地处理图形数据。GCN 可以沿着图形上的边缘执行滤波器操作&#xff0c;将每个节点的特征向量进…

中国艺术孙溟㠭篆刻作品《活着》

人人为生活挣扎着&#xff0c;做着不想做的事&#xff0c;说着不想说的话&#xff0c;为生活低头弯腰委屈求全人生苦多甜少&#xff0c;何时了&#xff01;何时了&#xff01;甜来人生到头了…… 孙溟㠭篆刻作品《活着》 孙溟㠭篆刻作品《活着》 孙溟㠭篆刻作品《活着》 文/九钵

python3GUI--我的翻译器By:PyQt5(附下载地址)

文章目录 一&#xff0e;前言二&#xff0e;展示1.主界面2.段落翻译3.单词翻译 三&#xff0e;设计1.UI设计2.软件设计3.参考 四&#xff0e;总结 一&#xff0e;前言 很早之前写过一篇python3GUI–翻译器By:PyQt5&#xff08;附源码&#xff09; &#xff0c;但是发现相关引擎…

设计模式之单例模式

单例模式 定义&#xff1a;保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点 引子&#xff1a;读取配置文件 很多地方要用到&#xff0c;如果每次都new 一个对象的话&#xff0c;会浪费内存资源。 改装成饿汉式&#xff08;饿汉式有线程并发问题&#xff0c…

【计算机网络】11、网桥(bridge)、集线器(hub)、交换机(switch)、路由器(router)、网关(gateway)

文章目录 一、网桥&#xff08;bridge)二、集线器&#xff08;hub&#xff09;三、交换机&#xff08;switch)四、路由器&#xff08;router&#xff09;五、网关&#xff08;gateway&#xff09; 对于hub&#xff0c;一个包过来后&#xff0c;直接将包转发到其他口。 对于桥&…

【Linux命令200例】cp用于复制文件和目录(常用)

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;本文已收录于专栏&#xff1a;Linux命令大全。 &#x1f3c6;本专栏我们会通过具体的系统的命令讲解加上鲜…