- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
此笔记是本人学习数据结构的笔记,持续更新中
优点:对于链表中一个给定的结点,可以从两个方向进行操作。在单向链表中,只有获得结点的前驱结点的指针,才能删除该结点。在双向链表中,每个结点都有一个指向前驱结点的指针,可以直接后退到前驱结点。
缺点:需要更多的空间开销。结点的插入或删除更加费时(需要更多指针的操作)。
public class DLLNode{
private DLLNode next;
private DLLNode previous;
public DLLNode(int data){
this.data=data;
}
public void setData(int data){
this.data=data;
}
public int getData(){
return data;
}
public void setNext(DLLNode next){
this.next=next;
}
public DLLNode getNext(){
return this.next;
}
public void setPrevious(DLLNode previous){
this.previous=previous;
}
public DLLNode getPrevious(){
return this.previous;
}
}
双向链表的插入操作分为以下3种情况:开头插入,末尾插入,中间插入
①将新结点的后继结点指向表头结点
②将新节点的前驱结点指向Null
③将表头的前驱结点更新为新结点
①将新节点的后继结点指向Null
②将新节点的前驱结点指向末尾结点
③更新末尾结点的后继结点使其指向新结点
先两边后中间
①新结点的后继结点指向需要插入新节点的位置结点的后继结点,新节点的前驱结点执行位置结点
②位置结点的后继结点指向新节点,位置结点的后继结点指向新结点
时间复杂度为O(n),因为最差情况下,可能需要删除链表的表尾结点。
空间复杂度为O(1),仅用于创建一个临时变量。
删除操作分为3种情况:删除表头的结点,删除中间的结点,删除表尾的结点
①创建一个临时结点,它与表头指向同一个结点
②修改表头结点,使其指向下一个结点,将表头结点的前驱结点更改为Null ,之后移除临时结点。
①遍历链表,在遍历时还要保存前驱结点的地址。
②改变表尾的前驱结点的后继指针为Null
①遍历链表,一旦找到,将前驱结点的next指针指向被删除结点的下一个结点。
②更改被删除结点的后继结点的前驱指针指向被删除结点的前驱结点。
③移除被删除的当前结点
时间复杂度为O(n),因为最差情况下,可能需要删除链表的表尾结点。
空间复杂度为O(1),仅用于创建一个临时变量。
循环链表没有结束标志。
循环链表可以通过标记为表头的结点进行访问。
int CircularListData(CLLNode headNode){
CLLNode CLLNode=headNode;
while(CLLNode!=null){
System.out.print(CLLNode.getData()+"->");
CLLNode=CLLNode.getNext();
if(CLLNode==headNode)break;
}
}
①创建一个新结点,初始化其next指针指向改结点本身
②更新新结点的next指针为表头结点。
③更新表头的前驱结点的next指针指向新结点
在循环链表中的表头前插入新结点和在表尾插入新结点的唯一区别就是在插入新结点后还需要更新指针。
①遍历循环链表,找到表尾结点及其前驱结点
②更新表尾的前驱结点的next指针使其指向表头结点
③移除表尾结点。
①遍历循环链表找到表尾结点。表尾结点是将要删除的表头结点的前驱结点。
②修改表头指针的值,使其指向后继结点。移除临时结点。
在双向链表常规的实现中,需要一个指向后继结点的正向指针和一个指向前驱结点的反向指针。这表明双向链表的结点由数据,一个指向后继结点的指针和一个指向前驱结点的指针构成。
public class ListNode{
private int data;
private ListNode ptrdiff;
}
ptrdiff指针字段包含后继结点的地址与前驱结点的地址的差。指针的差通过异或运算来实现。
ptrdiff=后继结点的地址^前驱结点的地址
表头结点的ptrdiff等于NULL与表头结点的后继结点的地址的异或。类似地,类似地,表尾结点的ptrdiff等于表尾结点的前驱结点的地址与Null的异或。
与数组相比,链表的最大优势在于,在任何位置插入元素的时间开销为O(1).然而,在链表中查找某个元素的时间开销则是O(n).松散链表为单向链表的简单表种。
松散链表中的每个结点存储多个元素(简称块)。而每一个块中的所有结点由循环链表连接在一起。
松散链表主要有两个优点,一个是时间方面的问题,另一是空间方面。
首先,如果每块中的元素个数适中(例如,最多一个缓存行的大小),那么通过改善内存局限性,能够获得显著更优的缓存性能。
其次,因为在松散链表中链接的大小仅为O(n/m),其中n等于松散链表中的元素的个数,m等于一个块中能够存储的元素个数,所以这也将节省大量的空间。当每个元素的大小较小时,效果会更加明显。
栈是一种用于存储数据的简单数据结构。数据入栈的次序是栈的关键。在现实生活中栈可以形象的比如成一堆盘子。
void push(int data) //将data数据插入栈
int pop() //删除并返回最后一个插入栈的元素
int top() //返回最后一个插入栈的元素,但不删除
int size() //返回存储在栈中元素的个数
int isEmpty() //判断栈中是否有元素
int isStackFull() //判断栈中是否存满元素
在执行操作时发生的错误称为异常。当操作不能执行时,会“抛出”异常。在栈抽象数据类型中,pop操作和top操作在栈空时是不能执行的。
一种线性的存储结构,对存储的结构只做查找和修改操作
当我们的数组容量满的时候,再次添加一个元素,会触发扩容机制,然后再将这个元素删除,又会触发缩减容量的机制。缩减容量过程会消耗资源。
解决:size==capacity/4是,才将capacity减半。
像栈一样,队列也是一种线性表,它的特性是先进先出,插入在一端,删除在另一端,就像排队一样,刚来的人入队要排在队尾,每次出队的都是队首的人。
散列表又叫哈希表或Hash表。
散列表是根据关键码值而直接进行访问的数据结构。也就是说,它通过把关键码映射到表中的一个位置来访问记录,以加快查找的速度。
这个映射函数叫做散列函数,存放记录的数组叫做散列表。
本质为一个函数,我们把它定义为hash(key),key就是元素的键值,通过hash函数得到的值就是散列值。
散列函数可以自己设计,需要遵循一些规则。
因为现实世界的key是无限的,散列值是经过一定的规则将key进行运算,然后得到的,冲突是无法避免的。
一旦遇到哈希冲突,就重新探索一个空闲位置,然后插入。
当我们往散列表中插入数据时,经过散列函数发现位置已经被占用了,我们就从当前位置开始,依次往后查找,直到找到空闲位置为止。
比如一个散列表的大小为 10,一个数据经过散列函数之后,到了下标为 8 的位置,但是发现这个位置已经有数据了,那么就依次往后遍历,如果到了尾部,还是没有找到空闲位置,那么就再从头开始找,直到找到空闲位置。
二次探索,和线性探索原理一样,先行探索每次的步长为 1 ,探索的下标依次为 hash(key)+0,hash(key)+1,hash(key)+2…,二次探索每次的步长变为原来的二次方,所以每次探索的下边为 hash(key)+0,hash(key)+12,hash(key)+22。
原来我们使用一个散列函数,双重散列,我们使用多个散列函数,我们先用第一个散列函数,如果计算得到的位置已经被占用,就使用第二个散列函数,以此类推,直到找到空闲时的位置。
链表法是一种更为常用的解决散列冲突的方法,比开放寻址法更加简单。在散列表中每个下标位置对应一个链表,所有经过散列函数得到的散列值相同的元素,我们都放到对应下标位置的链表中。
插入元素时,经过散列函数得到散列值,然后插入到对应下标位置的链表中即可,时间复杂度为 O(1)。查找和删除同样的对对应位置的链表进行操作,对应的时间复杂度和链表的长度有关系,也就是 O(n)。
跳表又叫跳跃列表,它允许快速查询,插入和删除一个有序连续元素的数据链表。跳跃列表的平均查找和插入时间复杂度都是O(logn)。快速查询是通过维护一个多层次的链表,且每一层链表中的元素是前一层链表元素的子集。一开始时,算法在最稀疏的层次进行搜索,直至需要查找的元素在该层两个相邻的元素中间。这时,算法将跳转到下一个层次,重复刚才的搜索,直到找到需要查找的元素为止。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-86GI41Lg-1626588706368)(…/…/.local/Image/image-20210714113550999.png)]
一张跳跃列表的示意图。每个带有箭头的框表示一个指针,而每行是一个稀疏子序列的链表;底部的编号框表示有序的数据列表。查找从顶部最稀疏的子序列向下进行,直至需要查找的元素在该层两个相邻的元素中间。
跳表相当于在链表的基础上,建立多层索引,来提高查找速度。
比如查找15,从第一级索引开始遍历,找到14,17,最后往下,一共遍历了7个结点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9EwS8s9f-1626588706370)(…/…/.local/Image/image-20210714114150209.png)]
如果从第二级索引开始找,一共遍历了6个结点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-orjrZnLD-1626588706372)(…/…/.local/Image/image-20210714114200191.png)]
树状图是一种数据结构,它是由n个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一颗倒挂的树,也就是说它是根朝上的,而叶朝下的。
它具有以下的特点:每个特点有零个或多个子结点;没有父节点的结点称为根结点;每一个非根节点有且只有一个父结点;除了根结点外,每个子结点可以分为多个不相交的子树;
树结构是非线性存储结构,存储的是具有“一对多”关系的数据元素的集合。
树的任意结点的子结点没有顺序关系
树的任意结点的子节点有顺序关系
树的任意结点至多包含两颗子树。
二叉树的遍历是指但从二叉树的根节点出发,按照某种次序访问二叉树中的所有结点,使得每个结点被访问一次,且紧被访问一次。
二叉树的访问次序可以分为四种:前序遍历 中序遍历 后序遍历 层次遍历
叶子结点都在同一层并且除叶子节点外的所有结点都有两个子结点。
对于一颗二叉树,假设其深度为d(d>1)。除第d层外的所有结点构成满二叉树,且第d层所有结点从左向右连续地紧密排列, 这样的二叉树被称为完全二叉树;最下层的结点都集中在该层最左边的若干位置上。
除了叶子结点外,都有两个子结点
在无向图中,若从顶点V到顶点W有路径存在,则称V和W是连通的。
若图G中任意两个顶点都是连通的,则称图G为连通图,否则称为非连通图。
无向图中的极大连通子图称为连通分量。
在有向图中,若从顶点V到顶点W和从顶点V之间都有路径,则称这个两个顶点是强连通的。
若图中任何一对顶点都是强连通的,则称为此图为强连通图。
有向图中的极大连通子图称为有向图的强连通分量。
以该顶点为一个端点的边的数目。
在有向图中,入度是以顶点V为终点的有向边的数目。
在有向图中,出度是以顶点V为起点的有向边的数目。
有向图的全部顶点的入度之和与出度之和相等,并且等于边数。
堆数据结构是一种数组对象,它可以被视为一棵完全二叉树结构,所以堆也叫做二叉堆。
字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串,所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较。
Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。
前缀树的3个基本性质:
字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串,所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较。
Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。
前缀树的3个基本性质:
初学者 android 问题。好的,我已经成功写入文件。例如。 //获取文件名 String filename = getResources().getString(R.string.filename
我已经将相同的图像保存到/data/data/mypackage/img/中,现在我想显示这个全屏,我曾尝试使用 ACTION_VIEW 来显示 android 标准程序,但它不是从/data/dat
我正在使用Xcode 9,Swift 4。 我正在尝试使用以下代码从URL在ImageView中显示图像: func getImageFromUrl(sourceUrl: String) -> UII
我的 Ubuntu 安装 genymotion 有问题。主要是我无法调试我的数据库,因为通过 eclipse 中的 DBMS 和 shell 中的 adb 我无法查看/data/文件夹的内容。没有显示
我正在尝试用 PHP 发布一些 JSON 数据。但是出了点问题。 这是我的 html -- {% for x in sets %}
我观察到两种方法的结果不同。为什么是这样?我知道 lm 上发生了什么,但无法弄清楚 tslm 上发生了什么。 > library(forecast) > set.seed(2) > tts lm(t
我不确定为什么会这样!我有一个由 spring data elasticsearch 和 spring data jpa 使用的类,但是当我尝试运行我的应用程序时出现错误。 Error creatin
在 this vega 图表,如果我下载并转换 flare-dependencies.json使用以下 jq 到 csv命令, jq -r '(map(keys) | add | unique) as
我正在提交一个项目,我必须在其中创建一个带有表的 mysql 数据库。一切都在我这边进行,所以我只想检查如何将我所有的压缩文件发送给使用不同计算机的人。基本上,我如何为另一台计算机创建我的数据库文件,
我有一个应用程序可以将文本文件写入内部存储。我想仔细看看我的电脑。 我运行了 Toast.makeText 来显示路径,它说:/数据/数据/我的包 但是当我转到 Android Studio 的 An
我喜欢使用 Genymotion 模拟器以如此出色的速度加载 Android。它有非常好的速度,但仍然有一些不稳定的性能。 如何从 Eclipse 中的文件资源管理器访问 Genymotion 模拟器
我需要更改 Silverlight 中文本框的格式。数据通过 MVVM 绑定(bind)。 例如,有一个 int 属性,我将 1 添加到 setter 中的值并调用 OnPropertyChanged
我想向 Youtube Data API 提出请求,但我不需要访问任何用户信息。我只想浏览公共(public)视频并根据搜索词显示视频。 我可以在未经授权的情况下这样做吗? 最佳答案 YouTube
我已经设置了一个 Twilio 应用程序,我想向人们发送更新,但我不想回复单个文本。我只是想让他们在有问题时打电话。我一切正常,但我想在发送文本时显示传入文本,以确保我不会错过任何问题。我正在使用 p
我有一个带有表单的网站(目前它是纯 HTML,但我们正在切换到 JQuery)。流程是这样的: 接受用户的输入 --- 5 个整数 通过 REST 调用网络服务 在服务器端运行一些计算...并生成一个
假设我们有一个名为 configuration.js 的文件,当我们查看内部时,我们会看到: 'use strict'; var profile = { "project": "%Projec
这部分是对 Previous Question 的扩展我的: 我现在可以从我的 CI Controller 成功返回 JSON 数据,它返回: {"results":[{"id":"1","Sourc
有什么有效的方法可以删除 ios 中 CBL 的所有文档存储?我对此有疑问,或者,如果有人知道如何从本质上使该应用程序像刚刚安装一样,那也会非常有帮助。我们正在努力确保我们的注销实际上将应用程序设置为
我有一个 Rails 应用程序,它与其他 Rails 应用程序通信以进行数据插入。我使用 jQuery $.post 方法进行数据插入。对于插入,我的其他 Rails 应用程序显示 200 OK。但在
我正在为服务于发布请求的 API 调用运行单元测试。我正在传递请求正文,并且必须将响应作为帐户数据返回。但我只收到断言错误 注意:数据是从 Azure 中获取的 spec.js const accou
我是一名优秀的程序员,十分优秀!