当前位置:首页 » 操作系统 » 数据结构算法实现

数据结构算法实现

发布时间: 2024-08-27 20:53:19

‘壹’ 图解:数据结构与算法之字典树

字典树(Trie树)这一数据结构是不太常见但是十分好用<typo id="typo-32" data-origin="而" ignoretag="true">而</typo>一种数据结构,博主也就是最近一段时间做了几道字节的题目才了解到字典树这一数据结构。并将自己的学习内容跟大家分享。

首先,何为字典树(Trie树)?顾名思义,就是在查询目标时,像字典一样按照一定排列顺序标准和步骤访问树的节点,举一个简单例子,英文字典查单词"He",那么第一步你肯定要按照a-z的顺序先找到h这个首字母,然后再按照相同顺序找到e。博主所要介绍的字典树就是类似字典这样的结构。

上述查找单词的过程就是不断查找与所查单词相同前缀的字符串,直至查找到所查单词的最后一个字母。因此,字典树又称为前缀树(prefix Tree)。

以hell、hi、new、nop为例建立一个字典树,构造如下

根据上文所述可以得到字典树的结构性质

根据以上三点来构造字典树。

字典树的构造其实较为简单,和一般树的构造没有太大区别。接下来将对字典树的插入、删除、查询操作进行分析与讲解。

在没有字典树的时候,我们需要先构建出字典树。

以插入hell为例:

再插入单词hit,过程如下,检查=>存在则访问/不存在则建立新节点再访问=>直到要插入的单词到达最后一个字符。

字典树的插入操作比较简单,不需要考虑太多排序问题。

正如上文所说,按照一定的标准进行查询目标字符串,每个节点都储存一个字符,根节点到达子节点路径组成的字符串即为该节点所对应的字符串,那么查询目标字符串时按照从根节点一步一步访问相应字符所在的节点,其实也就是匹配字符串前缀的过程。

如下图,在字典树中,查询"hell",

[图片上传失败...(image-f028c4-1611057619223)]

如果在该字典中查询no

删除操作相对于插入与查询复杂一点,但是也很简单,删除的前提是单词已经存在于字典树。

删除字典树节点的操作需要考虑目标字符串最后一个字符是否是树中的叶子节点。

因为一个单词可能是另一个单词的前缀部分,如果不是叶子节点,我们只需要把该单词的单词标志位清空即可,无需删除整个“树枝”。

比如,想要删除"no"这个单词

比如,想要删除"hell"这个单词,与第一种删除相同,只不过是从最后一个节点,'l'节点是叶子节点,开始往上进行节点删除操作。

比如,想要删除"hi",那么与前两种其实一致,访问到叶子节点'i',删除叶子节点,并向上访问,访问到'h',由于删除'i'以后,'h'依然不是叶子节点,因此不再继续删除节点。

比如,想要删除"nop",与前几种类似,先访问到叶子节点'p'删除,然后上移发现'o'是叶子节点,然而'o'有单词标记位,所以,这里不再继续删除。

有上面几种删除操作,我们得到了删除的标准:

了解了这么多字典树的各种操作,相信你对字典树的用途有个大概了解了,字典树最大作用是用于==字符串的各种匹配==,前缀匹配(模糊搜索),字符串查找(字典)等等。

博主只打出了“涓涓清泉”四个关键字,其搜索列表返回了诸多以涓涓清泉为首的选项

顾名思义,就是一个单纯的字典而已,不多举例。

字典树的构建,通过利用空间换时间的思想以及字符串的公共前缀减少无效的字符串比较操作从而使得插入和查找字符串变得高效.其插入或者查找的时间复杂度为O(n),n为字符串长度。

当然,字典树有着它的弊端,当所插入的单词没有很多公共前缀时,字典树的构建变得十分复杂和低效。

字典树的难度不是很大,但却是一种十分有用的数据结构,掌握之后,对于解决一些有关字符串匹配、公共前缀的问题十分有帮助。

当然我们也说了,字典树有着自己的弊端,由于用空间换时间,如果遇到了一堆公共前缀很少的单词进行字典树构造时,空间需求就显得十分大了。

‘贰’ 数据结构中有哪些基本算法

数据结构中最基本的算法有:查找、排序、快速排序,堆排序,归并排序,,二分搜索算法
等等。

1、用的最多也是最简单的数据结构是线性表。

2、有前途的又难数据结构是图 。

3、常用的80%算法是排序和查找。

‘叁’ bfs可以使用哪种数据结构实现

BFS(广度优先搜索)算法可以使用队列(Queue)这种数据结构实现。

在BFS过程中,我们将待访问的节点放入队列中,并按照广度优先的顺序依次访问队列中的节点。每当访问一个节点时,我们将其所有相邻节点加入队列中,并更新它们到起点的距离。这样,队列中的节点始终是距离起点最近的节点,从而实现了广度优先搜索。

另外,在实际实现中,还可以使用邻接表(Adjacency List)来表示图中的节点和边。邻接表是一种链式存储结构,可以用来存储图中每个节点的相邻节点及其权重。通过邻接表,我们可以方便地实现BFS和DFS(深度优先搜索)算法。

BFS算法的主要应用场景包括:

1、连通性分析:判断图中两个节点之间是否存在连通性,即是否存在一条路径连接这两个节点。

2、最小生成树:Prim算法和Kruskal算法的基础思想与BFS类似,都是通过逐步添加边来构建一棵包含所有节点的生成树。

3、最短路径计算:Dijkstra算法和Floyd-Warshall算法也采用了与BFS类似的思想,通过逐步扩展已访问节点来寻找最短路径。

BFS算法的实现过程中,通常使用队列数据结构来存储待访问的节点。此外,还需要使用一个visited数组来记录已访问过的节点,以及一个distance数组来记录每个节点到起点的距离。在实际应用中,还可以使用邻接表来表示图中的节点和边,以方便进行遍历操作。

以上内容参考网络-宽度优先搜索

‘肆’ python数据结构与算法-哈希map的实现及原理

1-collections.MutableMapping

1.1 概念:这是什么?

大家可能想知道这一串英文是什么意思?其实只需要了解在collections库当中有一个非常重要的抽象基类MutableMappin

g,专门用于实现map的一个非常有价值的工具。后边我们会用到它。

2-我们的map基类


2.1 实现这个类

这个基类其实也就是确定了键值对的属性,并且存储了基本的比较方法。它的对象就是一个键值对咯。这个很好理解。有点类似object的感觉。

3-通过map基类实现的无序映射

给大家看一个上边的例子,这个例子来源于网络,自己改了改,能用,更加详细而已,凑合看.

4-Python哈希表的实现的基类

4.1 咱有话直说:上才(代)艺(码)

如果还不知道哈希表概念的同xio,请参考 python进阶之数据结构与算法–中级-哈希表(小白piao分享) 。废话不多说,咱们撸代码:

OK了,基本的哈希表就实现了,其实仔细想想很容易,但是自己要能实现还是要理解哈希表的本质哦,外加一定量的练习才可以熟练掌握,练习的目的就是为了熟练而已。

5-分离链表实现的具体哈希map类

说明:这玩意只是一种降低冲突的手段,上一节提过,降低冲突最好的地方是发生在元组进入桶的时候,所以想必大家猜到了,接下来的分离链表也就是为了self._bucket_xxxxxxx系列方法做准备。这里之所以在上边使用@abstractmethod就是为了继承实现,目的可以实现多种将冲突的哈希表。分离链表的概念上一节也有的。
“见码入面”(借鉴:见字如面这个电视节目,有兴趣可以看看,还不错的):

6-用线性探测处理冲突的哈希map类

这种方式的好处不需要再去借助其他额外的赋值结构来表示桶。结构更加简单。不会再像上一种方法还要让桶是一个UnsortedTableMap的对象。
代码如下:

‘伍’ 一文带你认识30个重要的数据结构和算法

数组是最简单也是最常见的数据结构。它们的特点是可以通过索引(位置)轻松访问元素。

它们是做什么用的?

想象一下有一排剧院椅。每把椅子都分配了一个位置(从左到右),因此每个观众都会从他将要坐的椅子上分配一个号码。这是一个数组。将问题扩展到整个剧院(椅子的行和列),您将拥有一个二维数组(矩阵)。

特性

链表是线性数据结构,就像数组一样。链表和数组的主要区别在于链表的元素不存储在连续的内存位置。它由节点组成——实体存储当前元素的值和下一个元素的地址引用。这样,元素通过指针链接。

它们是做什么用的?

链表的一个相关应用是浏览器的上一页和下一页的实现。双链表是存储用户搜索键哗显示的页面的完美数据结构。

特性

堆栈是一种抽象数据类型,它形式化了受限访问集合的概念。该限制遵循 LIFO(后进先出)规则。因此,添加到堆栈中的最后一个元素是您从中删除的第一个元素。

堆栈可以使用数组或链表来实现。

它们是做什么用的?

现实生活中最常见的例子是在食堂中将盘子叠放在宽枝一起。位于顶部的板首先被移除。放置在最底部的盘子是在堆栈中保留时间最长的盘子。

堆栈最有用的一种情况是您需要获取给定元素的相反顺序。只需将它们全部推入堆栈,然后弹出它们。

另一个有趣的应用是有效括号问题。给定一串括号,您可以使用堆栈检查它们是否匹配。

特性

队列是受限访问集合中的另一种数据类型,就像前面讨论的堆栈一样。主要区别在于队列是按照FIFO(先进先出)模型组织的:队列中第一个插入的元素是第一个被移除的元素。队列可以使用固定长度的数组、循环数组或链表来实现。

它们是做什么用的?

这种抽象数据类型 (ADT) 的最佳用途当然是模拟现实生活中的队列。例如,在呼叫中心应用程序中,队列用于保存等待从顾问那里获得帮助的客户——这些客户应该按照他们呼叫的顺序获得帮助。

一种特殊且非常重要的队列类型是优先级队列。元素根据与它们关联的“优先级”被引入队列:具有最高优先级的元素首先被引入队列。这个 ADT 在许多图算法(Dijkstra 算法、BFS、Prim 算法、霍夫曼编码 )中是必不可少的。它是使用堆实现的。

另一种特殊类型的队列是deque 队列(双关语它的发音是“deck”)。可以从队列的两端插入/删除元素。

特性

Maps (dictionaries)是包含键集合和值集合的抽象数据类型。每个键都有一个与之关联的值。

哈希表是一种特殊类型的映射。它使用散列函数生成一个散列码,放入一个桶或槽数组:键被散列,结果散列指示值的存储位置。

最常见的散列函数(在众多散列函数中)是模常数函数。例如,如果常量是 6,则键 x 的值是x%6。

理想情况下,散列函数会将每个键分配给一个唯一的桶,但他们的大多数设计都采用了不完善的函数,这可能会导致具有相同生成值的键之间发生冲突。这种碰撞总是以某种方式适应的。

它们是做什么用的?

Maps 最着名的应用是语言词典。语言中的每个词都为其指定了定义。它是使用有序映射实现的(其键按字母顺序排列)。

通讯录也是一张Map。每个名字都有一个分配给它的电话号码。

另一个有用的应用是值的标准化。假设我们要为一天中的每一分钟(24 小时 = 1440 分钟)分配一个从 0 到 1439 的索引。哈希函数将为h(x) = x.小时*60+x.分钟。

特性

术语:

因为maps 是使用自平衡红黑树实现的(文章后面会解释),所以所有操作都在 O(log n) 内完成;所有哈希表操作都是常量。

图是表示一对两个集合的非线性数据结构:G={V, E},其中 V 是顶点(节点)的集合,而 E 是边(箭头)的集合。节点是由边互连的值 - 描述两个节点之间的依赖关系(有时与成本/距离相关联)的线。

图有两种主要类型:有稿巧行向图和无向图。在无向图中,边(x, y)在两个方向上都可用:(x, y)和(y, x)。在有向图中,边(x, y)称为箭头,方向由其名称中顶点的顺序给出:箭头(x, y)与箭头(y, x) 不同。

它们是做什么用的?

特性

图论是一个广阔的领域,但我们将重点介绍一些最知名的概念:

一棵树是一个无向图,在连通性方面最小(如果我们消除一条边,图将不再连接)和在无环方面最大(如果我们添加一条边,图将不再是无环的)。所以任何无环连通无向图都是一棵树,但为了简单起见,我们将有根树称为树。

根是一个固定节点,它确定树中边的方向,所以这就是一切“开始”的地方。叶子是树的终端节点——这就是一切“结束”的地方。

一个顶点的孩子是它下面的事件顶点。一个顶点可以有多个子节点。一个顶点的父节点是它上面的事件顶点——它是唯一的。

它们是做什么用的?

我们在任何需要描绘层次结构的时候都使用树。我们自己的家谱树就是一个完美的例子。你最古老的祖先是树的根。最年轻的一代代表叶子的集合。

树也可以代表你工作的公司中的上下级关系。这样您就可以找出谁是您的上级以及您应该管理谁。

特性

二叉树是一种特殊类型的树:每个顶点最多可以有两个子节点。在严格二叉树中,除了叶子之外,每个节点都有两个孩子。具有 n 层的完整二叉树具有所有2ⁿ-1 个可能的节点。

二叉搜索树是一棵二叉树,其中节点的值属于一个完全有序的集合——任何任意选择的节点的值都大于左子树中的所有值,而小于右子树中的所有值。

它们是做什么用的?

BT 的一项重要应用是逻辑表达式的表示和评估。每个表达式都可以分解为变量/常量和运算符。这种表达式书写方法称为逆波兰表示法 (RPN)。这样,它们就可以形成一个二叉树,其中内部节点是运算符,叶子是变量/常量——它被称为抽象语法树(AST)。

BST 经常使用,因为它们可以快速搜索键属性。AVL 树、红黑树、有序集和映射是使用 BST 实现的。

特性

BST 有三种类型的 DFS 遍历:

所有这些类型的树都是自平衡二叉搜索树。不同之处在于它们以对数时间平衡高度的方式。

AVL 树在每次插入/删除后都是自平衡的,因为节点的左子树和右子树的高度之间的模块差异最大为 1。 AVL 以其发明者的名字命名:Adelson-Velsky 和 Landis。

在红黑树中,每个节点存储一个额外的代表颜色的位,用于确保每次插入/删除操作后的平衡。

在 Splay 树中,最近访问的节点可以快速再次访问,因此任何操作的摊销时间复杂度仍然是 O(log n)。

它们是做什么用的?

AVL 似乎是数据库理论中最好的数据结构。

RBT(红黑树) 用于组织可比较的数据片段,例如文本片段或数字。在 Java 8 版本中,HashMap 是使用 RBT 实现的。计算几何和函数式编程中的数据结构也是用 RBT 构建的。

在 Windows NT 中(在虚拟内存、网络和文件系统代码中),Splay 树用于缓存、内存分配器、垃圾收集器、数据压缩、绳索(替换用于长文本字符串的字符串)。

特性

最小堆是一棵二叉树,其中每个节点的值都大于或等于其父节点的值:val[par[x]]

热点内容
罪恶都市安卓内置菜单在哪里下载 发布:2024-11-25 07:09:51 浏览:706
数据库附加数据库 发布:2024-11-25 07:08:08 浏览:403
支付宝支付密码如何修改 发布:2024-11-25 06:38:47 浏览:923
java开发要学习什么技术 发布:2024-11-25 06:20:28 浏览:1000
java猿 发布:2024-11-25 06:18:36 浏览:127
如何刷安卓44 发布:2024-11-25 06:18:32 浏览:529
安卓手机怎么限制app时间 发布:2024-11-25 06:14:15 浏览:403
福建虚拟服务器管理软件云服务器 发布:2024-11-25 06:05:46 浏览:106
android加载图片 发布:2024-11-25 06:05:00 浏览:168
linux的ls 发布:2024-11-25 05:47:56 浏览:844