数据结构与算法C
文章平均质量分 59
Kegi_
励志学好C++的小白
展开
-
快速排序思想,算法代码,复杂度分析以及优化
不过,随机就有些撞大运的感觉,万一没撞成功,随机到了依然是很小或很大的关键字怎么办呢?就空间复杂度来说,主要是递归造成的栈空间的使用,最好情况,递归树的深度为log2n,其空间复杂度也就为O(logn),最坏情况,需要进行n-1递归调用,其空间复杂度为O(n),平均情况,空间复杂度也为O(logn)。通过这段代码的模拟,大家应该能够明白,Partition函数,其实就是将选取的pivotkey不断交换,将比它小的换到它的左边,比它大的换到它的右边,它也在交换中不断更改自己的位置,直到完全满足这个要求为止。原创 2024-02-12 19:36:40 · 871 阅读 · 0 评论 -
非递归实现归并排序
非递归的迭代方法,避免了递归时深度为log2n的栈空间,空间只是用到申请归并临时用的TR数组,因此空间复杂度为O(n),并且避免递归也在时间性能上有一定的提升,应该说,使用归并排序时,尽量考虑用非递归方法。函数接收一个原始序列SR,一个用于存放结果的序列TR,以及两个参数s和n,表示对SR的相邻长度为s的子序列进行归并,归并结果存放在TR中,n表示SR中的元素个数。综上所述,这段代码实现了归并排序算法的归并段落操作,通过迭代地将SR中相邻长度为s的子序列归并到TR中,最终得到更长的有序子序列。原创 2024-02-12 13:50:01 · 319 阅读 · 0 评论 -
归并排序算法相关代码及其复杂度分析
并将结果放到TR1[1]~TR1[n]中,这需要将待排序序列中的所有记录扫描一遍,因此耗费O(n)时间,而由完全二叉树的深度可知,整个归并排序需要进行次,因此,总的时间复杂度为O(nlogn),而且这是归并排序算法中最好、最坏、平均的时间性能。在循环内部,通过比较SR[i]和SR[j]的大小,将较小的元素放入TR中的当前位置k,并将相应的指针i或j递增1,指向下一个要比较的元素。函数接收一个原始序列SR,一个用于存放结果的序列TR1,以及两个参数s和t,表示对原始序列SR的s到t位置进行归并排序。原创 2024-02-12 13:43:30 · 954 阅读 · 0 评论 -
堆排序说明及其算法相关代码与复杂度分析
当然,这绝不是简单的堆砌。它使用了一个循环,从序列的末尾开始,每次将堆顶记录(即关键字最大的元素)与当前未经排序子序列的最后一个记录交换位置,并对前面的部分重新调整为大顶堆。在正式排序时,第i次取堆顶记录重建堆需要用O(logi)的时间(完全二叉树的某个结点到根结点的距离为),并且需要取n-1次堆顶记录,因此,重建堆的时间复杂度为O(nlogn)。综上所述,这段代码实现了堆排序算法的排序过程,通过不断地将堆顶元素与未排序子序列的最后一个元素交换位置,并对前部分重新调整为大顶堆,最终实现了对整个序列的排序。原创 2024-02-12 13:28:28 · 797 阅读 · 0 评论 -
希尔排序原理,算法及其相关代码,以及复杂度分析
这不对呀,比如我们现在有序列是{9,1,5,8,3,7,4,6,2},现在将它分成三组,{9,1,5},{8,3,7},{4,6,2},哪怕将它们各自排序排好了,变成{1,5,9},{3,7,8},{2,4,6},再合并它们成{1,5,9,3,7,8,2,4,6},此时,这个序列还是杂乱无序,谈不上基本有序,要排序还是重来一遍直接插入有序,这样做有用吗?希尔排序的优点是相比于普通插入排序,它可以在一开始就对部分数据进行排序,从而提前进行了部分的排序优化,可以减少逆序对的数量。/2),要好于直接排序的O(原创 2024-02-12 12:37:36 · 1010 阅读 · 0 评论 -
直接插入排序算法(相关代码)及其复杂度分析
也就是要排序的表本身就是有序的,比如纸牌拿到后就是{2,3,4,5,6},那么我们比较次数,其实就是代码第6行每个L.r[i]与L.r[i-1]的比较,共比较了(n-1)sigma(i=2, n, 1)次,由于每次都是L.r[i]>L.r[i-1],因此没有移动的记录,时间复杂度为O(n)。4.此时,第10行就是在移动完成后,空出了空位,然后第11行L.r[j+1]=L.r[0],将哨兵的3赋值给j=0时的L.r[j+1],也就是说,将扑克牌3放置到L.r[1]的位置。6.再次循环,此时i=4。原创 2024-02-11 17:31:31 · 335 阅读 · 0 评论 -
简单选择排序
分析它的时间复杂度发现,无论最好最差的情况,其比较次数都是一样的多,第i趟排序需要进行n-i次关键字的比较,此时需要比较sigma(i=1, n-1, n-i)=(n-1)+(n-2)+...+1=n(n-1)/2次。而对于交换次数而言,当最好的时候,交换为0次,最差的时候,也就初始降序时,交换次数为n-1次,基于最终的排序时间是比较与交换的次数总和,因此,总的时间复杂度依然为O(n2)。首先,从顺序表L的第2个元素开始,依次遍历到最后一个元素(i的取值范围为1到L的长度-1)。原创 2024-02-11 17:25:35 · 379 阅读 · 0 评论 -
冒泡排序的改进实现优化以及相关复杂度分析
事实上,在不断循环的过程中,除了将关键字1放到第一的位置,我们还将关键字2从第九位置提到了第三的位置,显然这一算法比前面的要有进步,在上十万条数据的排序过程中,这种差异会体现出来。假设我们待排序的关键字序列是{9,1,5,8,3,7,4,6,2},当i=1时,9与1交换后,在第一位置的1与后面的关键字比较都小,因此它就是最小值。依然假设我们待排序的关键字序列是{9,1,5,8,3,7,4,6,2},当i=1时,变量j由8反向循环到1,逐个比较,将较小值交换到前面,直到最后找到最小值放置在了第1的位置。原创 2024-02-11 17:11:36 · 825 阅读 · 0 评论 -
排序的基本概念及其分类及用到的相关结构和函数
排序:假设含有n个记录的序列为{r1,r2,......,rn},其相应的关键字分别为{k1,k2,......,kn},需确定1,2,......,n的一种排列p1,p2,......,pn,使其相应的关键字满足kp1≤kp2≤......≤kpn(非递减或非递增)关系,即使得序列成为一个按关键字有序的序列{rp1,rp2,......,rpn},这样的操作就称为排序。从这个例子也可看出,多个关键字的排序最终都可以转化为单个关键字的排序,因此,我们这里主要讨论的是单个关键字的排序。原创 2024-02-11 17:01:48 · 348 阅读 · 0 评论 -
散列表查找实现及其性能分析(解释说明及相关代码)
α标志着散列表的装满的程度。比如我们前面的例子,如果你的散列表长度是12,而填入表中的记录个数为11,那么此时的装填因子α=11/12=0.9167,再填入最后一个关键字产生冲突的可能性就非常之大。为了做到这一点,通常我们都是将散列表的空间设置得比查找集合大,此时虽然是浪费了一定的空间,但换来的是查找效率的大大提升,总的来说,还是非常值得的。散列函数的好坏直接影响着出现冲突的频繁程度,不过,由于不同的散列函数对同一组随机的关键字,产生冲突的可能性是相同的,因此我们可以不考虑它对平均查找长度的影响。原创 2024-02-10 21:49:59 · 345 阅读 · 0 评论 -
处理散列冲突的方法(四种)
考虑深一步,如果发生这样的情况,当最后一个key=34,f(key)=10,与22所在的位置冲突,可是22后面没有空位置了,反而它的前面有一个空位置,尽管可以不断地求余数后得到结果,但效率很差。对于关键字集合{12,67,56,16,25,37,22,29,15,47,48,34},我们用前面同样的12为除数,进行除留余数法,可得到结构,此时,已经不存在什么冲突换址的问题,无论有多少个冲突,都只是在当前位置给单链表增加结点的问题。计算key=37时,发现f(37)=1,此时就与25所在的位置冲突。原创 2024-02-10 21:41:05 · 896 阅读 · 0 评论 -
散列函数的构造方法
如果我们的关键字是位数较多的数字,比如我们的11位手机号“130xxxx1234”,其中前三位是接入号,一般对应不同运营商公司的子品牌,如130是联通如意通、136是移动神州行、153是电信等;比如我们的关键字是9876543210,散列表表长为三位,我们将它分为四组,987|654|321|0,然后将它们叠加求和987+654+321+0=1962,再求后3位得到散列地址为962。再比如关键字是4321,那么它的平方就是18671041,抽取中间的3位就可以是671,也可以是710,用做散列地址。原创 2024-02-10 21:29:22 · 810 阅读 · 0 评论 -
散列表查找(哈希表)概述,定义及其查找步骤
对于顺序表查找时,我们曾经说过,如果你要查找某个关键字的记录,就是从表头开始,挨个的比较记录a[i]与key的值是“=”还是“≠”,直到有相等才算是查找成功,返回i。最终我们的目的都是为了找到那个i,其实也就是相对的下标,再通过顺序存储的存储位置计算方法,LOC(ai)=LOC(a1)+(i-1)×c,也就是通过第一个元素内存存储位置加上i-1个单元位置,得到最后的内存地址。一个班级几十个学生,他们的性别有男有女,你用关键字“男”去查找,对应的有许多学生的记录,这显然是不合适的。整个散列过程其实就是两步。原创 2024-02-10 21:09:46 · 371 阅读 · 0 评论 -
B+树(在B树的基础上对其进行解释说明)
B+树的结构特别适合带有范围的查找。可是在B树结构中,我们往返于每个结点之间也就意味着,我们必须得在硬盘的页面之间进行多次访问,而且我们每次经过结点遍历时,都会对结点中的元素进行一次遍历,这就非常糟糕。,我们就从根结点出发,与B树的查找方式相同,只不过即使在分支结点找到了待查找的关键字,它也只是用来索引的,不能提供实际记录的访问,还是需要到达包含此。如果我们是需要从最小关键字进行从小到大的顺序查找,我们就可以从最左侧的叶子结点出发,不经过分支结点,而是延着指向下一叶子的指针就可遍历所有的关键字。原创 2024-02-10 20:59:27 · 318 阅读 · 0 评论 -
内存、硬盘和B树之间关系
当需要访问硬盘上的数据时,B树提供了高效的索引和检索方法,以减少硬盘的访问时间。B树通过多层次的节点组织硬盘上的数据,使得查找、插入和删除都能够以较快的速度进行。通过B树的索引,可以快速定位到硬盘上存储的数据块,并将其加载到内存中进行操作和处理。总结起来,内存、硬盘和B树之间的关系是:内存提供了快速的数据存储和操作能力,硬盘提供了大容量的永久性存储,而B树作为一种高效的索引结构,连接了内存和硬盘,实现了快速的数据访问和操作。内存、硬盘和B树之间存在着紧密的关系,它们在数据存储和访问中起着重要的作用。原创 2024-02-10 20:54:27 · 331 阅读 · 0 评论 -
B树的相关解释说明
Ai(i=0,2,...,n)为指向子树根结点的指针,且指针Ai-1所指子树中所有结点的关键字均小于Ki(i=1,2,...,n),An所指子树中所有结点的关键字均大于Kn,n(≤n≤m-1)为关键字的个数(或n+1为子树的个数)。结点最大的孩子数目称为B树的阶(order),因此,2-3树是3阶B树,2-3-4树是4阶B树。我们的外存,比如硬盘,是将所有的信息分割成相等大小的页面,每次硬盘读写的都是一个或多个完整的页面,对于一个硬盘来说,一页的长度可能是211到214个字节。所有叶子结点都位于同一层次。原创 2024-02-07 20:10:42 · 345 阅读 · 0 评论 -
2-3-4树
2-3-4树是2-3树的概念扩展,包括了4结点的使用。右子树包含大于最大元素的元素。如果该位置是一个4结点,则将其分裂为两个2结点或者一个2结点和一个3结点,然后递归调整树的结构。在2-3-4树中,每个结点可以是2结点、3结点或4结点。总结而言,2-3-4树是一种多路搜索树,扩展了2-3树的概念,引入了4结点来提供更高的容量和更好的平衡性。2-3-4树的平衡性保证了每个操作的时间复杂度都是O(log n),其中n是树中元素的个数。它是2-3树的扩展,引入了4结点的概念,以提供更高的容量和更好的平衡性。原创 2024-02-07 18:10:51 · 357 阅读 · 0 评论 -
2-3树(高效性与平衡性)
其中,拆分节点的中间元素会被提升为根节点的元素,拆分节点的左边元素会成为根节点的左子节点,拆分节点的右边元素会成为根节点的右子节点。- 如果该结点的双亲是2结点,并且它的右孩子也是2结点,需要进行整体的结构变换。总结而言,删除2-3树中的元素时,根据不同的情况进行相应的处理,包括直接删除叶子上的元素、处理2结点的情况、处理3结点的情况以及处理非叶子分支结点的情况。- 如果该结点的双亲也是2结点,并且双亲拥有一个3结点的右孩子,可以进行左旋操作,将6作为双亲,4作为6的左孩子,7作为6的右孩子。原创 2024-02-07 17:33:54 · 843 阅读 · 0 评论 -
多路查找树(B树)
内存一般都是由硅制的存储芯片组成,这种技术的每一个存储单位代价都要比磁存储技术昂贵两个数量级,因此基于磁盘技术的外存,容量比内存的容量至少大两个数量级。试想一下,为了要在一个拥有几十万个文件的磁盘中查找一个文本文件,你设计的算法需要读取磁盘上万次还是读取几十次,这是有本质差异的。在这里,每一个结点可以存储多少个元素,以及它的孩子数的多少是非常关键的。这就使得内存存取外存次数非常多,这显然成了时间效率上的瓶颈,这迫使我们要打破每一个结点只存储一个元素的限制,为此引入了多路查找树的概念。原创 2024-02-07 17:21:11 · 304 阅读 · 0 评论 -
平衡二叉树实现算法
如果我们需要查找的集合本身没有顺序,在频繁查找的同时也需要经常的插入和删除操作,显然我们需要构建一棵二叉排序树,但是不平衡的二叉排序树,查找效率是非常低的,因此我们需要在构建时,就让这棵二叉排序树是平衡二叉树,此时我们的查找时间复杂度就为O(logn),而插入和删除也为O(logn)。此函数代码的意思是说,当传入一个二叉排序树P,将它的左孩子结点定义为L,将L的右子树变成P的左子树,再将P改成L的右子树,最后将L替换P成为根结点。在第8行,将它们的BF值都改为0,表示调整后的平衡状态。原创 2024-02-06 16:55:12 · 336 阅读 · 0 评论 -
平衡二叉树说明及其实现原理
那什么叫做高度平衡呢?意思是说,要么它是一棵空树,要么它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1。平衡二叉树构建的基本思想就是在构建二叉排序树的过程中,每当插入一个结点时,先检查是否因插入而破坏了树的平衡性,若是,则找出最小不平衡子树。在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。距离插入结点最近的,且平衡因子的绝对值大于1的结点为根的子树,我们称为最小不平衡子树。原创 2024-02-06 16:35:04 · 358 阅读 · 0 评论 -
二叉排序树总结
二叉排序树的平衡问题是指在插入或删除元素后,保持树的形状尽可能平衡,使得树的深度尽量小,从而提高查找的效率。左旋操作是指将一个节点的右子树提升为根节点,该节点成为新根节点的左子树,新根节点的左子树成为该节点的右子树。右旋操作是指将一个节点的左子树提升为根节点,该节点成为新根节点的右子树,新根节点的右子树成为该节点的左子树。通过以上的旋转操作,平衡二叉树可以保持树的形状尽可能平衡,使得树的深度尽量小,从而提高查找的效率。7. 同插入操作一样,根据具体的情况进行左旋或右旋操作,直到所有的节点都平衡。原创 2024-02-06 12:10:51 · 353 阅读 · 0 评论 -
二叉排序树删除操作
需要注意的是,这段代码只实现了删除结点*p,并未进行二叉排序树的调整,即删除结点后的二叉排序树可能不满足二叉排序树的性质。如果左子树为空,则只需要将*p的右子树重接到*p的位置上,并释放*p的内存空间,完成删除操作。1. 首先判断*p的右子树是否为空,如果为空,则只需要将*p的左子树重接到*p的位置上,并释放*p的内存空间,完成删除操作。从这段代码也可以看出,我们其实是在找删除结点的前驱结点替换的方法,对于用后继结点来替换,方法上是一样的。- 如果s是*q的右孩子,则将s的左子树重接到*q的右孩子上。原创 2024-02-06 12:04:59 · 407 阅读 · 0 评论 -
二叉排序树插入操作
如果你调用函数是“In-sertBST(&T,93);”,那么结果就是FALSE,如果是“InsertBST(&T,95);”,那么一定就是在93的结点增加一个右孩子95,并且返回True。在你的大脑里,是否已经有一幅随着循环语句的运行逐步生成这棵二叉排序树的动画图案呢?如果不能,那只能说明你还没真理解它的原理。有了二叉排序树的查找函数,那么所谓的二叉排序树的插入,其实也就是将关键字放到树中的合适位置而已,代码如下。有了二叉排序树的插入代码,我们要实现二叉排序树的构建就非常容易了。原创 2024-02-06 11:46:00 · 378 阅读 · 0 评论 -
二叉树排序
此时,递归调用SearchBST函数,传入T的左孩子节点T->lchild作为新的根节点,key不变,将T作为双亲节点f传入,指针p不变。此时,递归调用SearchBST函数,传入T的右孩子节点T->rchild作为新的根节点,key不变,将T作为双亲节点f传入,指针p不变。如果查找不成功,则指针p将指向查找路径上访问的最后一个结点(即查找到的最近节点),并返回FALSE。是二叉树,然后它采用了递归的定义方法,再者,它的结点间满足一定的次序关系,左子树结点一定比其双亲结点小,右子树结点一定比其双亲结点大。原创 2024-02-06 11:35:21 · 356 阅读 · 0 评论 -
字符串在数据结构中通常被表示为向量(数组)的形式,而不是其他结构
而其他数据结构,如链表,不支持快速的随机访问,需要遍历到指定位置才能获取字符,效率较低。例如,可以直接修改指定位置的字符,或者在数组末尾添加新的字符。而其他数据结构,如链表,修改和拼接需要遍历节点,效率较低。尽管向量(数组)是一种较为常见的字符串表示方式,但在某些特定的场景下,其他数据结构也可以用于表示字符串。向量(数组)是一种连续存储的数据结构,可以将字符串的字符按顺序存储在数组中,便于访问和处理。其他数据结构,如链表,需要使用指针进行节点之间的连接,不是连续存储,会增加额外的空间开销。原创 2024-02-02 15:57:14 · 357 阅读 · 0 评论 -
线性索引查找产生以及三种线性索引方式(稠密索引、分块索引和倒排索引)
稠密索引是指在线性索引中,将数据集中的每个记录对应一个索引项,小例子和稠密索引还是略有不同,家里的东西毕竟少,小本子再多也就几十页,全部翻看完就几分钟时间,而稠密索引要应对的可能是成千上万的数据,因此对于稠密索引这个索引表来说,索引项一定是按照关键码有序的排列。是这个记录号不定长,比如上例有7个单词的文章编号只有一个,而“book”、“friend”、“good”有两个文章编号,若是对多篇文章所有单词建立倒排索引,那每个单词都将对应相当多的文章编号,维护比较困难,插入和删除操作都需要作相应的处理。原创 2024-02-02 13:57:08 · 878 阅读 · 0 评论 -
斐波那契查找及其相关实例代码
还有比较关键的一点,折半查找是进行加法与除法运算(mid=(low+high)/2),插值查找进行复杂的四则运算(mid=low+(high-low)*(key-a[low])/(a[high]-a[low])),而斐波那契查找只是最简单加减法运算(mid=low+F[k-1]-1),在海量数据的查找过程中,这种细微的差别可能会影响最终的查找效率。综上所述,该代码实现了使用斐波那契数列进行查找的算法,通过将数组长度扩展到满足斐波那契数列的要求,并以斐波那契数列的划分进行二分查找的方式,提高了查找效率。原创 2024-02-02 13:40:28 · 331 阅读 · 0 评论 -
有序表查找
因此,折半查找的时间复杂度是对数级别的,相比于顺序查找的线性级别O(n),效率显著提高。在最坏的情况下,即目标值不存在或者是有序表中的最左边或最右边的元素,需要进行log2n次比较才能确定目标值不存在,时间复杂度为O(logn)。首先,我们将这个数组的查找过程绘制成一棵二叉树,如果查找的关键字不是中间记录47的话,折半查找等于是把静态有序查找表分成了两棵子树,即查找结果只需要找其中的一半数据记录即可,等于工作量少了一半,然后继续折半查找,效率当然是非常高了。有序表的维护:折半查找要求有序表的顺序存储。原创 2024-02-02 10:45:59 · 387 阅读 · 0 评论 -
顺序查找算法及其优化
对于这种顺序查找算法来说,查找成功最好的情况就是在第一个位置就找到了,算法时间复杂度为O(1),最坏的情况是在最后一位置才找到,需要n次比较,时间复杂度为O(n),当查找不成功时,需要n+1次比较,时间复杂度为O(n)。否则一定在最终的a[0]处等于key,此时返回的是0,即说明a[1]~a[n]中没有关键字key,查找失败。很显然,顺序查找技术是有很大缺点的,n很大时,查找效率极为低下,不过优点也是有的,这个算法非常简单,对静态查找表的记录没有任何要求,在一些小型数据的查找时,是可以适用的。原创 2024-02-02 09:41:14 · 404 阅读 · 0 评论 -
查找表以及按操作方式将其分为的两大类(静态查找表、动态查找表)
比如网络时代的新名词,如反应年轻人生活的“蜗居”、“蚁族”、“孩奴”、“啃老”等,以及“X客”系列如博客、播客、闪客、黑客、威客等,如果需要将它们收录到汉语词典中,显然收录时就需要查找它们是否存在,以及找到如果不存在时应该收录的位置。在计算机科学中,查找(Searching)是指根据给定的某个值,在查找表(Search Table)中确定一个其关键字等于给定值的数据元素(或记录)。若表中存在这样的一个记录,则称查找是成功的,此时查找的结果给出整个记录的信息,或指示该记录在查找表中的位置。原创 2024-02-02 09:31:19 · 506 阅读 · 0 评论 -
AOV网(Activity-On-Vertex Network)和AOE网(Activity-On-Edge Network)的异同
而AOE网则需要引入事件节点,用邻接表表示图,每个边表示活动及其持续时间,顶点表示事件及其最早开始时间和最迟开始时间等。AOV网更关注活动的依赖关系和执行顺序,而AOE网更关注活动的持续时间和项目的最短完成时间。1. 定义:AOV网是将活动表示为图中的顶点,活动之间的依赖关系表示为有向边。而AOE网是将活动表示为图中的边,边上的权值表示活动的持续时间,顶点表示事件(事件指的是活动的起始和结束时间)。4. 并发活动:在AOV网中,并发活动可以被表示为互不相连的顶点。原创 2024-02-01 17:41:33 · 786 阅读 · 0 评论 -
拓扑排序算法及其相关代码
考虑到算法过程中始终要查找入度为0的顶点,我们在原来顶点表结点结构中,增加一个入度域in,其中in就是入度的数字。分析整个算法,对一个具有n个顶点e条弧的AOV网来说,第8~10行扫描顶点表,将入度为0的顶点入栈的时间复杂为O(n),而之后的while循环中,每个顶点进一次栈,出一次栈,入度减1的操作共执行了e次,所以整个算法的时间复杂度为O(n+e)。从AOV网中选择一个入度为0的顶点输出,然后删去此顶点,并删除以此顶点为尾的弧,继续重复此步骤,直到输出全部顶点或者AOV网中不存在入度为0的顶点为止。原创 2024-02-01 17:14:22 · 351 阅读 · 0 评论 -
拓扑排序介绍
通过拓扑排序,可以根据活动之间的依赖关系,确定活动的前后顺序,确保按照正确的顺序执行活动,从而保证项目的顺利进行。通过拓扑排序,可以清晰地了解各个活动之间的依赖关系,将活动划分为不同的阶段或阶段,更好地组织和管理项目,确保项目按计划进行。在项目管理中,通过拓扑排序确定活动的顺序,可以有效地安排任务的执行顺序和优先级,确保重要任务优先完成,从而提高项目的整体效率和质量。通过拓扑排序确定活动的顺序,可以合理安排资源的分配,避免资源的浪费和冲突,提高效率和资源利用率。无环,即是图中没有回路的意思。原创 2024-02-01 16:54:54 · 347 阅读 · 0 评论 -
AOV网中不能存在回路的原因
存在回路意味着可以通过一系列活动的依赖关系回到原始的活动,或者说存在一个活动能够通过其他活动的依赖关系回到自己。如果在AOV网中存在回路,会导致循环依赖的情况,即无法确定活动的执行顺序。2. 执行顺序不确定:回路存在意味着活动之间存在循环依赖,无法确定每个活动的执行顺序。因此,为了保证项目能够按照预期的顺序进行,并能够确定项目的最短完成时间,AOV网不能存在回路。1. 循环依赖:如果存在回路,就存在一条路径可以从一个活动出发,经过若干其他活动,最终回到原始的活动,形成循环依赖。原创 2024-02-01 15:23:53 · 326 阅读 · 0 评论 -
最短路径-迪杰斯特拉(Dijkstra)算法
这就好比,你吃了七个包子终于算是吃饱了,就感觉很不划算,前六个包子白吃了,应该直接吃第七个包子,于是你就去寻找可以吃一个就能饱肚子的包子,能够满足你的要求最终结果只能有一个,那就是用七个包子的面粉和馅做的一个大包子。在每一轮迭代中,选择距离数组中距离最小的顶点v,将其加入集合S,并更新起始顶点到其邻接顶点的距离。对此,我们现在再来介绍另一个求最短路径的算法——弗洛伊德(Floyd),它求所有顶点到所有顶点的时间复杂度也是O(n3),但其算法非常简洁优雅,能让人感觉到智慧的无限魅力。它的思路大体是这样的。原创 2024-02-01 13:07:56 · 296 阅读 · 0 评论 -
最小生成树及其经典算法(普里姆算法和克鲁斯卡尔算法)
9.第28~35行,j循环由1至8,因k=1,查找邻接矩阵的第v1行的各个权值,与low-cost的对应值比较,若更小则修改low-cost值,并将k值存入adjvex数组中。2.第6~7行我们分别给这两个数组的第一个下标位赋值为0,adjvex[0]=0其实意思就是我们现在从顶点v0开始(事实上,最小生成树从哪个顶点开始计算都无所谓,我们假定从v0开始),lowcost[0]=0就表示v0已经被纳入到最小生成树中,之后凡是lowcost数组中的值被设置为0就是表示此下标的顶点被纳入最小生成树。原创 2024-02-01 11:57:15 · 963 阅读 · 0 评论 -
图的遍历的两种算法及其相关代码
是一种用于遍历或搜索图的算法,其基本思想是从图的某个顶点开始,沿着一条路径尽可能深入地访问图中的顶点,直到到达一个没有未访问过的邻接顶点为止,然后返回并选择下一个未访问的顶点进行访问,重复这个过程,直到所有的顶点都被访问到。在栈实现中,使用一个栈来存储需要遍历的顶点,从栈顶取出顶点进行访问,然后将其未访问的邻接顶点压入栈中,重复这个过程,直到栈为空。它从一个起始顶点开始,首先访问该顶点,然后依次访问与起始顶点相邻的所有顶点,再依次访问与这些相邻顶点相邻的所有顶点,以此类推,直到图中所有顶点都被访问。原创 2024-02-01 11:29:41 · 1181 阅读 · 0 评论 -
图的多种存储结构及其代码
他创建一家公司,承接美国客户的视频监控任务,因为美国的黑夜就是中国的白天,利用互联网,他的员工白天上班就可以监控到美国仓库夜间的实际情况,如果发生了像火灾、偷盗这样的突发事件,及时电话到美国当地相关人员处理。考虑有向图的优化存储结构,对于无向图的邻接表的问题:如果我们在无向图的应用中,关注的重点是顶点,那么邻接表是不错的选择,但如果我们更关注边的操作,比如对已访问过的边做标记,删除某一条边等操作,那就意味着,需要找到这条边的两个边表结点进行操作,这其实还是比较麻烦的。对于有向图,邻接表的结构类似。原创 2024-02-01 11:00:33 · 785 阅读 · 0 评论 -
图的抽象数据类型
图作为一种数据结构,它的抽象数据类型带有自己特点,正因为它的复杂,运用广泛,使得不同的应用需要不同的运算集合,构成不同的抽象数据操作。我们这里就来看看图的基本操作。原创 2024-02-01 10:18:58 · 324 阅读 · 0 评论