Prim算法与穷举算法的时间复杂度分析
- 格式:doc
- 大小:61.00 KB
- 文档页数:4
邻接表普里姆算法时间复杂度邻接表普里姆算法是一种用于解决最小生成树问题的算法。
在该算法中,我们需要给定一个带权无向图,然后找出一个包含所有顶点且边权值之和最小的树。
它的时间复杂度是多少呢?让我们来探讨一下。
邻接表是一种常用的图的表示方法。
在邻接表中,每个顶点都对应一个链表,链表中存储了与该顶点相邻的顶点的信息。
而普里姆算法就是利用邻接表来实现的。
普里姆算法的基本思想是从一个顶点开始,逐步选择与当前树连接的具有最小权值的边的顶点,直到所有的顶点都被加入到树中。
具体步骤如下:1. 初始化一个空的树和一个空的边集合。
2. 随机选择一个顶点作为起始顶点,并将其加入到树中。
3. 将与起始顶点相邻的边加入到边集合中。
4. 从边集合中选择权值最小的边,并将其连接的顶点加入到树中。
5. 将该边从边集合中移除。
6. 重复步骤4和步骤5,直到所有的顶点都被加入到树中。
那么,这个算法的时间复杂度是多少呢?让我们来分析一下。
初始化树和边集合的时间复杂度是O(1)。
然后,在每一次选择最小权值边的过程中,我们需要遍历整个边集合,找到权值最小的边。
对于一个包含V个顶点的图,边集合中最多有V-1条边,因为最小生成树是一个包含V-1条边的树。
所以,遍历边集合的时间复杂度是O(V-1)。
接下来,将连接的顶点加入到树中的操作需要遍历邻接表中的链表,找到与当前顶点相邻的顶点。
对于一个包含V个顶点的图,邻接表中最多有V个链表,每个链表中最多有V-1个顶点。
所以,遍历邻接表的时间复杂度是O(V^2)。
重复步骤4和步骤5,直到所有的顶点都被加入到树中。
由于每次选择最小权值边时,边集合中的边都会减少一条,所以重复的次数最多为V-1次。
因此,重复步骤4和步骤5的时间复杂度是O(V-1)。
邻接表普里姆算法的时间复杂度可以表示为:O(1) + O(V-1) + O(V^2) + O(V-1)其中,O(1)表示初始化的时间复杂度,O(V-1)表示选择最小权值边的时间复杂度,O(V^2)表示遍历邻接表的时间复杂度,O(V-1)表示重复步骤4和步骤5的时间复杂度。
一、选择题1、二分搜索算法是利用〔 A 〕实现的算法。
A、分治策略B、动态规划法C、贪心法D、回溯法2、以下不是动态规划算法根本步骤的是〔 A 〕。
A、找出最优解的性质B、构造最优解C、算出最优解D、定义最优解3、最大效益优先是〔 A 〕的搜索方式。
A、分支界限法B、动态规划法C、贪心法D、回溯法4. 回溯法解旅行售货员问题时的解空间树是〔 B 〕。
A、子集树B、排列树C、深度优先生成树D、广度优先生成树5.以下算法常以自底向上的方式求解最优解的是〔 B 〕。
A、备忘录法B、动态规划法C、贪心法D、回溯法6、衡量一个算法好坏的标准是〔C 〕。
A 运行速度快B 占用空间少C 时间复杂度低D 代码短7、以下不可以使用分治法求解的是〔D 〕。
A 棋盘覆盖问题B 选择问题C 归并排序D 0/1背包问题8. 实现循环赛日程表利用的算法是〔 A 〕。
A、分治策略B、动态规划法C、贪心法D、回溯法9.下面不是分支界限法搜索方式的是〔 D 〕。
A、广度优先B、最小消耗优先C、最大效益优先D、深度优先10.以下算法常以深度优先方式系统搜索问题解的是〔 D 〕。
A、备忘录法B、动态规划法C、贪心法D、回溯法11.备忘录方法是那种算法的变形。
〔 B 〕A、分治法B、动态规划法C、贪心法D、回溯法12.最长公共子序列算法利用的算法是〔 B 〕。
A、分支界限法B、动态规划法C、贪心法D、回溯法13.实现棋盘覆盖算法利用的算法是〔 A 〕。
A、分治法B、动态规划法C、贪心法D、回溯法14.下面是贪心算法的根本要素的是〔 C 〕。
A、重叠子问题B、构造最优解C、贪心选择性质D、定义最优解15.回溯法的效率不依赖于以下哪些因素〔 D 〕A.满足显约束的值的个数B. 计算约束函数的时间C. 计算限界函数的时间D. 确定解空间的时间16.下面哪种函数是回溯法中为防止无效搜索采取的策略〔 B 〕A.递归函数 B.剪枝函数C.随机数函数 D.搜索函数17.〔 D 〕是贪心算法与动态规划算法的共同点。
采用普里姆算法和克鲁斯卡尔算法,求最小生成树-回复普里姆算法和克鲁斯卡尔算法是求解最小生成树问题的两种重要方法。
本文将详细介绍这两种算法的原理和步骤,并比较它们的优缺点和适用场景。
一、普里姆算法普里姆算法(Prim's Algorithm)是一种贪心算法,用于求解带权无向连通图的最小生成树。
它的基本思想是从一个起始顶点开始,逐步向最小代价的边添加顶点,直到生成一颗包含所有顶点的最小生成树。
下面是普里姆算法的具体步骤:1. 随机选择一个顶点作为起始顶点,并将其添加到最小生成树集合中。
2. 从最小生成树集合中已有的顶点出发,寻找与其相连的边中具有最小权值的顶点,将该顶点添加到最小生成树集合中。
3. 重复第二步,直到最小生成树集合包含所有顶点为止。
普里姆算法的时间复杂度为O(V^2),其中V为顶点数。
它的优点是简单易懂、容易实现,并且适用于稠密图。
然而,普里姆算法对于稀疏图的效率较低,因为需要频繁地搜索和更新权值最小的边。
二、克鲁斯卡尔算法克鲁斯卡尔算法(Kruskal's Algorithm)是一种基于边的贪心算法,用于求解带权无向连通图的最小生成树。
它的基本思想是通过选择代价最小的边,并判断是否会形成环路,最终构建出一颗最小生成树。
下面是克鲁斯卡尔算法的具体步骤:1. 将图中的所有边按照权值从小到大进行排序。
2. 依次选择权值最小的边,判断如果添加该边会形成环路,则将其舍弃;否则将其添加到最小生成树的边集合中。
3. 重复第二步,直到最小生成树的边数等于顶点数减一为止。
克鲁斯卡尔算法的时间复杂度为O(ElogE),其中E为边数。
相比普里姆算法,克鲁斯卡尔算法适用于稀疏图,并且对于大规模图的求解效率更高。
然而,克鲁斯卡尔算法的缺点是在构建最小生成树时需要尝试的边较多,因此在边数较多的情况下,算法的效率可能不高。
三、比较与总结普里姆算法和克鲁斯卡尔算法都是求解最小生成树问题的经典算法,它们各自具有不同的优点和适用场景。
最⼩⽣成树---普⾥姆算法(Prim算法)和克鲁斯卡尔算法(Kruskal算法)最⼩⽣成树的性质:MST性质(假设N=(V,{E})是⼀个连通⽹,U是顶点集V的⼀个⾮空⼦集,如果(u,v)是⼀条具有最⼩权值的边,其中u属于U,v属于V-U,则必定存在⼀颗包含边(u,v)的最⼩⽣成树)普⾥姆算法(Prim算法)思路:以点为⽬标构建最⼩⽣成树1.将初始点顶点u加⼊U中,初始化集合V-U中各顶点到初始顶点u的权值;2.根据最⼩⽣成树的定义:从n个顶点中,找出 n - 1条连线,使得各边权值最⼩。
循环n-1次如下操作:(1)从数组lowcost[k]中找到vk到集合U的最⼩权值边,并从数组arjvex[k] = j中找到该边在集合U中的顶点下标(2)打印此边,并将vk加⼊U中。
(3)通过查找邻接矩阵Vk⾏的各个权值,即vk点到V-U中各顶点的权值,与lowcost的对应值进⾏⽐较,若更⼩则更新lowcost,并将k存⼊arjvex数组中以下图为例#include<bits/stdc++.h>using namespace std;#define MAXVEX 100#define INF 65535typedef char VertexType;typedef int EdgeType;typedef struct {VertexType vexs[MAXVEX];EdgeType arc[MAXVEX][MAXVEX];int numVertexes, numEdges;}MGraph;void CreateMGraph(MGraph *G) {int m, n, w; //vm-vn的权重wscanf("%d %d", &G->numVertexes, &G->numEdges);for(int i = 0; i < G->numVertexes; i++) {getchar();scanf("%c", &G->vexs[i]);}for(int i = 0; i < G->numVertexes; i++) {for(int j = 0; j < G->numVertexes; j++) {if(i == j) G->arc[i][j] = 0;else G->arc[i][j] = INF;}}for(int k = 0; k < G->numEdges; k++) {scanf("%d %d %d", &m, &n, &w);G->arc[m][n] = w;G->arc[n][m] = G->arc[m][n];}}void MiniSpanTree_Prim(MGraph G) {int min, j, k;int arjvex[MAXVEX]; //最⼩边在 U集合中的那个顶点的下标int lowcost[MAXVEX]; // 最⼩边上的权值//初始化,从点 V0开始找最⼩⽣成树Tarjvex[0] = 0; //arjvex[i] = j表⽰ V-U中集合中的 Vi点的最⼩边在U集合中的点为 Vjlowcost[0] = 0; //lowcost[i] = 0表⽰将点Vi纳⼊集合 U ,lowcost[i] = w表⽰ V-U中 Vi点到 U的最⼩权值for(int i = 1; i < G.numVertexes; i++) {lowcost[i] = G.arc[0][i];arjvex[i] = 0;}//根据最⼩⽣成树的定义:从n个顶点中,找出 n - 1条连线,使得各边权值最⼩for(int i = 1; i < G.numVertexes; i++) {min = INF, j = 1, k = 0;//寻找 V-U到 U的最⼩权值minfor(j; j < G.numVertexes; j++) {// lowcost[j] != 0保证顶点在 V-U中,⽤k记录此时的最⼩权值边在 V-U中顶点的下标if(lowcost[j] != 0 && lowcost[j] < min) {min = lowcost[j];k = j;}}}printf("V[%d]-V[%d] weight = %d\n", arjvex[k], k, min);lowcost[k] = 0; //表⽰将Vk纳⼊ U//查找邻接矩阵Vk⾏的各个权值,与lowcost的对应值进⾏⽐较,若更⼩则更新lowcost,并将k存⼊arjvex数组中for(int i = 1; i < G.numVertexes; i++) {if(lowcost[i] != 0 && G.arc[k][i] < lowcost[i]) {lowcost[i] = G.arc[k][i];arjvex[i] = k;}}}int main() {MGraph *G = (MGraph *)malloc(sizeof(MGraph));CreateMGraph(G);MiniSpanTree_Prim(*G);}/*input:4 5abcd0 1 20 2 20 3 71 2 42 3 8output:V[0]-V[1] weight = 2V[0]-V[2] weight = 2V[0]-V[3] weight = 7最⼩总权值: 11*/时间复杂度O(n^2)克鲁斯卡尔算法(Kruskal算法)思路:以边为⽬标进⾏构建最⼩⽣成树在边集中依次寻找最⼩权值边,若构建是不形成环路(利⽤parent数组记录各点的连通分量),则将其添加到最⼩⽣成树中。
第七章图习题答案基础知识:7.1 在图7.23所示的各无向图中:(1)找出所有的简单环。
(2)哪些图是连通图?对非连通图给出其连通分量。
(3)哪些图是自由树(或森林)?答:(1)所有的简单环:(同一个环可以任一顶点作为起点)(a)1231(b)无(c)1231、2342、12341(d)无(2)连通图:(a)、(c)、(d)是连通图,(b)不是连通图,因为从1到2没有路径。
具体连通分量为:(3)自由树(森林):自由树是指没有确定根的树,无回路的连通图称为自由树:(a)不是自由树,因为有回路。
(b)是自由森林,其两个连通分量为两棵自由树。
(c)不是自由树。
(d)是自由树。
7.2 在图7.24(下图)所示的有向图中:(1) 该图是强连通的吗? 若不是,则给出其强连通分量。
(2) 请给出所有的简单路径及有向环。
(3) 请给出每个顶点的度,入度和出度。
(4) 请给出其邻接表、邻接矩阵及逆邻接表。
答:(1)该图是强连通的,所谓强连通是指有向图中任意顶点都存在到其他各顶点的路径。
(2)简单路径是指在一条路径上只有起点和终点可以相同的路径:有v1v2、v2v3、v3v1、v1v4、v4v3、v1v2v3、v2v3v1、v3v1v2、v1v4v3、v4v3v1、v3v1v4、另包括所有有向环,有向环如下:v1v2v3v1、v1v4v3v1(这两个有向环可以任一顶点作为起点和终点)(3)每个顶点的度、入度和出度:D(v1)=3ID(v1)=1OD(v1)=2D(v2)=2 ID(v2)=1OD(v2)=1D(v3)=3 ID(v3)=2OD(v3)=1D(v4)=2 ID(v4)=1OD(v4)=1(4)邻接表:(注意边表中邻接点域的值是顶点的序号,这里顶点的序号是顶点的下标值-1) vertex firstedge next┌─┬─┐┌─┬─┐┌─┬─┐0│v1│─→│ 1│─→│ 3│∧│├─┼─┤├─┼─┤└─┴─┘1│v2│─→│ 2│∧│├─┼─┤├─┼─┤2│v3│─→│ 0│∧│├─┼─┤├─┼─┤3│v4│─→│ 2│∧│└─┴─┘└─┴─┘逆邻接表:┌─┬─┐┌─┬─┐0│v1│─→│ 2│∧│├─┼─┤├─┼─┤1│v2│─→│ 0│∧│├─┼─┤├─┼─┤┌─┬─┐2│v3│─→│ 1│─→│ 3│∧│├─┼─┤├─┼─┤└─┴─┘3│v4│─→│ 0│∧│└─┴─┘└─┴─┘邻接矩阵:0 1 0 10 0 1 01 0 0 00 0 1 07.3 假设图的顶点是A,B...,请根据下述的邻接矩阵画出相应的无向图或有向图。
prim算法实验报告Prim算法实验报告一、引言Prim算法是一种常用的最小生成树算法,用于在一个加权连通图中生成一棵覆盖所有顶点且边权和最小的树。
本实验旨在通过编程实现Prim算法,并分析其时间复杂度和实际应用。
二、算法描述Prim算法的基本思想是从一个初始顶点开始,逐步扩展生成树,每次选择与当前生成树连接的最短边对应的顶点,并将其加入生成树中,直到所有顶点都被加入为止。
具体步骤如下:1. 选择一个初始顶点作为生成树的根节点。
2. 在剩余的顶点中,选择与当前生成树连接的最短边对应的顶点,并将其加入生成树中。
3. 更新生成树与剩余顶点之间的边权,即若新加入的顶点到其他剩余顶点的距离更短,则更新距离。
4. 重复步骤2和步骤3,直到所有顶点都被加入生成树为止。
三、实验过程本实验使用C++编程语言实现Prim算法。
首先,通过邻接矩阵表示给定的加权连通图,其中顶点间的距离用边的权值表示,无连接的顶点间距离设为无穷大。
然后,选择一个初始顶点作为生成树的根节点,并将其加入生成树中。
接下来,循环执行以下步骤,直到所有顶点都被加入生成树为止:1. 找到与当前生成树连接的最短边对应的顶点,将其加入生成树中。
2. 更新生成树与剩余顶点之间的边权。
3. 记录每次加入生成树的边及其权值。
四、实验结果本实验使用了一个具体的加权连通图进行测试。
测试结果显示,Prim算法能够正确生成最小生成树,并且生成的树的边权和确实是最小的。
通过对比不同初始顶点的选择,发现生成树的形状可能会有所差异,但边权和仍然是最小的。
五、时间复杂度分析Prim算法的时间复杂度主要取决于两个因素:顶点数和边数。
在每次循环中,需要找到与当前生成树连接的最短边,这个过程需要遍历所有剩余顶点,时间复杂度为O(V)。
总共需要执行V次循环,因此Prim算法的时间复杂度为O(V^2)。
如果使用优先队列来优化寻找最短边的过程,时间复杂度可以降至O((V+E)logV),其中E为边数。
Prim算法优化策略Prim算法是一种用于求解最小生成树问题的经典算法。
它通过逐步选择与当前生成树相连的最小权值边来构造最小生成树。
在实际应用中,Prim算法的时间复杂度较高,因此需要一些优化策略来提高算法效率。
一、延迟更新策略在Prim算法中,每次选择最小权值的边添加到生成树中后,就需要更新与新增节点相邻的边的权值。
而延迟更新策略可以将这个更新过程延迟到后面再进行,避免了反复更新造成的时间浪费。
具体实现时,可以使用一个优先队列(最小堆)来存储与生成树相邻的边,每次从队列中取出权值最小的边,将其添加到生成树中,并标记其相邻节点已访问。
当队列为空时,表示所有节点都已加入生成树,算法结束。
延迟更新策略可以避免多次更新同一条边的权值,大大减少了更新操作的次数,提高了算法效率。
二、稠密图优化策略Prim算法在处理稠密图(边数接近或等于节点数的平方)时,时间复杂度较高。
为了解决这个问题,可以使用邻接矩阵来表示图,同时使用一个数组来记录每个节点到生成树的最小权值。
具体实现时,可以将邻接矩阵中的边权值初始化为一个较大的值,然后从第一个节点开始,选择与当前节点最近的未访问节点,并更新它们到生成树的最小权值。
通过这种方式,可以有效地减少对稠密图中未访问节点的搜索次数,提高算法效率。
三、堆优化策略Prim算法中,每次需要选择与当前生成树相连的最小权值边,这个过程可以通过堆来实现,以减少对边权值的搜索时间。
具体实现时,可以使用一个最小堆来存储边,堆中的每个元素都是一个包含边的两个节点和权值的数据结构。
首先将第一个节点加入生成树中,然后将其相邻边添加到堆中。
每次从堆中取出权值最小的边,将其相邻节点加入生成树,并将新的边添加到堆中。
通过使用堆结构,可以快速找到最小权值的边,提高算法的效率。
综上所述,Prim算法可以通过延迟更新策略、稠密图优化策略和堆优化策略等方法来进行优化,提高算法的效率。
在实际应用中,根据具体的问题和数据特点,选择适当的优化策略可以进一步加快算法的执行速度,提高算法的实用性和可扩展性。
一、引言Prim算法是一种常用于解决最小生成树问题的算法,其核心在于通过不断选择与当前最小生成树集合相邻的最短边来逐步构建最小生成树。
在Prim算法中,cost算法扮演着重要的角色,用于计算各个节点到已选节点的最短距离,并选择其中最小的距离作为下一步要添加到最小生成树集合中的节点。
本文将对Prim算法和cost算法进行概述,以深入探讨其原理和应用。
二、Prim算法原理1.最小生成树的概念:最小生成树是一个图的生成树中,边的权值之和最小的生成树。
Prim算法即用于寻找图的最小生成树的算法之一。
2.Prim算法步骤:a. 从任意起始节点开始,将其加入最小生成树集合中;b. 不断找出与当前最小生成树集合相邻的最小距离节点,并将其加入最小生成树集合;c. 重复步骤b,直到所有节点都被加入最小生成树集合。
3.使用cost算法选择下一个节点:a. cost算法用于计算各个节点到已选节点的最短距离;b. 总是选择距离最小的节点加入最小生成树集合。
三、cost算法详解1.算法用途:在Prim算法中,cost算法用于计算各个节点到已选节点的最短距离,并选择其中最小的距离作为下一个要添加到最小生成树集合中的节点。
2.实现方法:常用的实现方法包括使用邻接矩阵或邻接表来表示图的结构,然后通过遍历节点和边来计算距离,并选择最小值。
3.时间复杂度分析:cost算法的时间复杂度与Prim算法的时间复杂度相同,通常为O(n^2)或O(nlogn),其中n为节点的数量。
四、Prim算法与cost算法的应用1.网络设计:Prim算法和cost算法常用于网络设计中,用于构建最小生成树,以实现网络最优化布线和资源分配。
2.电路设计:Prim算法和cost算法也常用于电路设计中,用于选择最优路径和最小成本的连接方式。
3.城市规划:在城市规划中,Prim算法和cost算法被用于确定最优的交通路线和城市布局。
五、总结1.Prim算法是一种用于寻找图的最小生成树的常用算法,其核心在于逐步选择与当前最小生成树集合相邻的最小边来构建最小生成树。
普里姆算法时间复杂度
普里姆算法(Prim's Algorithm)是用于求最小生成树的一种算法。
该
算法是由捷克数学家普里姆于1956年提出的。
它是一种贪婪算法,其
核心思想是:每一步从当前的顶点的未访问的邻边中找到最小的权重
的边,将此边加入子集,最终集合中的边构成一棵树,这就是最小生
成树。
普里姆算法的时间复杂度:
(1)时间复杂度为O(ElogV):
该算法开始时,先从某个起点顶点开始,然后依次将其邻边加入最小
生成树,直到所有顶点都属于该树,才结束,在每次选择最小权重邻
边时,要处理顶点的全部邻边,需要O(E)时间,由于每次添加一个顶
点后,有O(V)的邻边需要加入候选集,需要O(VLogV)时间来完成,
这让普里姆算法的时间复杂度为O(Elogv)。
(2)空间复杂度为O(V+E):
在普里姆算法中,为了确定最短路径,需要开辟两个数组,一个表示
每个顶点是否被访问,一个表示每条边的权重。
空间的大小就是要开
辟的数组的大小,也就是说,时间复杂度为O(V+E)。
(3)复杂度分析:
普里姆算法的时间复杂度是O(ElogV),此时的操作数量取决于边的数
量E以及顶点的数量V,在最糟糕的情况下,时间复杂度为O(E2∗V),
最佳的情况下,时间复杂度为O(E∗V),而空间复杂度为O(V+E)。
普
里姆算法相比其他基于分支限界算法而言,可以更快得到最小生成树。
prim计算实验报告Prim计算实验报告引言:Prim算法是一种常用的图论算法,用于解决最小生成树问题。
在本次实验中,我们通过使用Prim算法,对一个给定的图进行计算,并得出最小生成树。
一、实验目的本次实验的目的是熟悉Prim算法的原理和实现方法,通过实际操作,了解算法的具体过程和效果。
同时,通过对比实验结果,探讨Prim算法在不同图结构下的优劣势。
二、实验方法1. 算法原理Prim算法是一种贪心算法,它从一个顶点开始,逐步扩展最小生成树的边集合,直到包含所有顶点为止。
具体步骤如下:(1)选择一个起始顶点,将其加入最小生成树的顶点集合。
(2)从与选定顶点相连的边中,选择一条权值最小的边,将其加入最小生成树的边集合。
(3)将新加入的顶点也加入最小生成树的顶点集合。
(4)重复步骤(2)和(3),直到最小生成树的顶点包含所有顶点。
2. 实验步骤(1)读取图的数据,构建邻接矩阵表示图的结构。
(2)选择一个起始顶点,将其加入最小生成树的顶点集合。
(3)从与选定顶点相连的边中,选择一条权值最小的边,将其加入最小生成树的边集合。
(4)将新加入的顶点也加入最小生成树的顶点集合。
(5)重复步骤(3)和(4),直到最小生成树的顶点包含所有顶点。
(6)输出最小生成树的边集合和权值。
三、实验结果我们选择了一个具有10个顶点和15条边的图进行实验。
经过计算,得出的最小生成树的边集合和权值如下:边集合:(1, 2),(1, 3),(2, 4),(2, 5),(3, 6),(4, 7),(4, 8),(5, 9),(6, 10)权值之和:28四、实验分析通过对比实验结果,我们可以发现Prim算法在求解最小生成树问题上具有以下优势:1. 时间复杂度低:Prim算法的时间复杂度为O(V^2),其中V为顶点数。
相比于其他算法,Prim算法的时间复杂度较低,适用于大规模图的计算。
2. 结果唯一性:Prim算法得到的最小生成树是唯一的,不受图的表示方式和顶点选择的影响。
Prim算法与穷举算法的时间复杂度分析
1、基本概念
在一个连通网的所有生成树中,各边的代价之和最小的那棵生成树称为该连通网的最小生成树。
最小生成树的性质:
设N=(V,{E}) 是一个连通网,U是顶点集V的一个非空子集,若(u,v)是一条具有最小权值的边,其中u属于U,v属于V,则存在一颗包含边(u,v)的最小生成树。
Prim算法就是利用这一性质来求最小生成树的,与穷举算法相比,Prim算法拥有更好的时间复杂度。
2、两种算法的思想
A.Prim算法思想:
1 首先将初始顶点u加入到U中,对其余每一个顶点i,将closedge[i]初始化为到点u的信息。
2 循环n-1次
1)从各组最小边closedge[v]中选出最小的最小边closedge[k0](v,k0属于V-U);
2) 将k加入到U中;
3) 更新剩余的每组最小边信息closedge[v](v属于V-U).
对于以v为中心的那组边,新增加了一条从k0到v的边,如果新边的权值比closedge[v].lowcost小,则将closedge[v].lowcost更新为新边的权值.
B.穷举算法思想:
1 首先将初始顶点u加入到U中,其余顶点加入到V中,h赋值为无穷大
2 穷举下列步骤
1) 从U中选择一个顶点a,从V中选择另外一个顶点b
2) 如果两个顶点间的距离不为无穷大,则将b加入到U中,从V中移除b,当前权值加上a-b的权值
3) 如果V不为空,转到1),如果V为空,而且权值比h小,将权值赋值给h
3.时间复杂度分析
A.Prim时间复杂度分析
1 n次
2 n次
2 1)n次
2 2)1次
2 3)n次
T(n)=n+n*(n+1+n)
=n+2n^2+n
=2O(n^2)
B.穷举复杂度分析
1 n次
2 (n-1)*1+(n-2)*2+…+1*(n-1) 次
2 1) n次
2 2) n次
2 3) n次
T(n)=n+((n-1)*1+(n-2)*2+…+1*(n-1))*(n+n+n) <=n+(n*n+n*n+…+n*n)*3n
=n+3n^3
=3O(n^3)
矩阵连乘动态规划算法
1、问题描述
给定n个矩阵{A1,A2,…,A n},其中A i与A i+1是可乘的,i=1,2,…,n-1。
要算出这n个矩阵的连乘积A1A2…A n。
由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序。
这种计算次序可以用加括号的方式来确定。
若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积。
完全加括号的矩阵连乘积可递归地定义为:
(1)单个矩阵是完全加括号的;
(2)矩阵连乘积A是完全加括号的,则A可表示为2个完全加括号的矩阵连乘积B和C的乘积并加括号,即A=(BC)。
例如,矩阵连乘积ABCD有5种不同的完全加括号的方式:A((BC)D),A(B(CD)),(AB)(CB),((AB)C)D,(A(BC))D。
每一种完全加括号的方式对应于一个矩阵连乘积的计算次序,这决定着作乘积所需要的计算量。
若A为50*10,B为10*40,C为40*30,D为30*5,则五种算法需要的计算次数分别为16000,10500,36000,87500,35000次。
由此可见,在计算矩阵连乘积时,加括号方式,即计算次序对计算量有很大的影响。
于是,自然提出矩阵连乘积的最优计算次序问题,即对于给定的相继n个矩阵{A1,A2,…,A n}(其中矩阵A i的维数为P i-1* P i,i=1,2,…,n),如何确定计算矩阵连乘积{A1,A2,…,A n}的计算次序(完全加括号方式),使得依此次序计算矩阵连乘积需要的数乘次数最少。
穷举搜索法的计算量太大,它不是一个有效的算法,本实验采用动态规划算法解矩阵连乘积的最优计算次序问题。
二、算法思路
动态规划算法的基本思想是将待求解问题分成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
与分治法不同的是,动态规划法经分解得到的子问题往往不是相互独立的,前一子问题的解为后一子问题的解提供有用的信息,可以用一个表来记录所有已解决的子问题的答案,不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。
本实验的算法思路是:
1 一个矩阵,运算0次
2 两组矩阵,运算次数为两组矩阵自身的运算次数之和再加上第一个矩阵的行数*最后一个矩阵的列数
3 矩阵连乘次数最少的算法,其中一部分的运算也是最少的(或者叫最优的)
由以上可以推出矩阵连乘最少算法的递归公式:
M in = M ik + M i+1 n + P(i-1)*P(k)*P(j)
使用递归公式,可以很快地找到最少计算次数的计算方法
主要的递归函数:
int calcu(int i,int j,int p[],char st[]){
int nmin=2147483647;
if(i==j){
char m[250];
gcvt(i,10,m);
//拼接"a"和i
strcat(st,"a");strcat(st,m);
return 0;
}else{
for(int k=i;k<j;k++){
char st1[250]={'\0'};
char st2[250]={'\0'};
int mp=calcu(i,k,p,st1)+calcu(k+1,j,p,st2)+p[i-1]*p[k]*p[j];
if (mp<nmin){
nmin=mp;
//拼接"(",st1,"*",st2,")"
st[0]='\0';
strcat(st,"(");strcat(st,st1);strcat(st,"*");strcat(st,st2);strcat(st,")");
}
}
}
return nmin;
}
三、计算结果。