掌握邻接矩阵Dijkstra算法与邻接表拓扑排序

版权申诉
0 下载量 8 浏览量 更新于2024-10-03 收藏 21.11MB ZIP 举报
资源摘要信息: "数据结构ch8-2_;拓扑排序_dijkstra_源码" 1. 概述 在数据结构领域中,拓扑排序和Dijkstra算法是两个非常重要的算法,分别用于解决不同的问题。拓扑排序用于有向无环图(DAG)中线性表示顶点的顺序,使得对于图中的任何一条有向边(u, v),顶点u都在顶点v之前。Dijkstra算法是一种用于在加权图中找到最短路径的算法,特别是在图中不存在负权边的情况下。 2. 拓扑排序 拓扑排序是针对有向无环图(DAG)的一种排序算法,它会返回一个线性顶点序列,这个序列满足图中的所有有向边都指向前面的顶点。拓扑排序的算法实现通常有以下几种方法: - 深度优先搜索(DFS):递归地进行DFS遍历,将每个节点存入一个栈中,最后逆序输出栈中的节点即可得到拓扑排序的结果。 - 入度表:维护一个入度表记录每个节点的入度,然后使用队列进行逐层遍历,每遍历一层,将入度为0的节点加入结果序列,同时更新其它节点的入度,直到队列为空。 3. Dijkstra算法 Dijkstra算法是一种用于单源最短路径的算法,它可以找到从一个顶点到图中所有其他顶点的最短路径。算法的基本思想是贪心策略,即在每一步都选择当前距离源点最近的一个顶点,并更新其邻接顶点的距离。Dijkstra算法通常可以分为以下步骤: - 初始化:将所有顶点分为两个集合,一个是已经找到最短路径的集合,另一个是未确定最短路径的集合。将起始点的距离设为0,其余所有点设为无穷大。 - 更新距离:遍历未确定最短路径的顶点集合,对于每一个顶点,检查通过它到每一个邻接点的距离是否小于当前记录的最短距离,如果是,则更新该邻接点的最短距离。 - 选择最小距离顶点:从未确定最短路径的顶点集合中选取一个距离源点最近的顶点,将其移动到已确定最短路径的顶点集合中。 - 重复以上步骤,直到所有的顶点都被处理。 4. 邻接矩阵与邻接表 在图的表示方法中,邻接矩阵和邻接表是两种常见的数据结构。它们用于存储图中顶点之间的关系。 - 邻接矩阵:是一个二维数组,其中每个元素表示两个顶点之间的边的权重。如果顶点i和顶点j之间有边相连,则矩阵的(i, j)元素非零;否则为零或无穷大(表示没有边)。 - 邻接表:是一种链表的集合,每个链表用于表示与某一顶点相连的所有顶点。通常是一个数组,数组的每个索引位置对应一个顶点,索引位置存储的是链表的头指针,链表中存储了所有邻接的顶点。 5. 源码分析 根据给定的标题,我们可以推断压缩包文件“数据结构ch8-2”包含了实现拓扑排序和Dijkstra算法的源码。在源码中,算法可能会使用邻接表来表示图的数据结构,因为邻接表在表示稀疏图时能够节省空间。 源码中的拓扑排序部分可能会采用入度表法,首先建立图中所有顶点的入度表,然后使用一个队列来迭代地找出所有入度为0的顶点,并将它们的邻接顶点的入度减1。当邻接顶点的入度降为0时,将其入队。重复此过程,直到队列为空,此时记录的顶点顺序即为拓扑排序的结果。 源码中的Dijkstra算法部分可能会使用优先队列(最小堆)来优化查找当前距离源点最近顶点的操作。在算法开始时,将源点的距离初始化为0,其他所有点的距离初始化为无穷大。然后重复执行以下操作:从未处理过的顶点集合中选取一个距离最小的顶点,更新其邻接点的距离,如果邻接点的距离被更新,则将该顶点及其距离放入优先队列中。 6. 应用场景 拓扑排序在很多领域都有广泛的应用,比如在软件工程中,用于描述依赖关系的任务调度;在编译原理中,用于语义分析和代码生成等。而Dijkstra算法则广泛应用于网络路由协议(如RIP,OSPF),以及各种导航系统中的路径规划。 7. 结论 综上所述,拓扑排序和Dijkstra算法是数据结构中非常基础且重要的算法,它们分别解决了有向无环图的线性排序和加权图中单源最短路径的问题。掌握这两种算法对于深入理解图论和算法设计有着重要的意义。在实际应用中,根据图的稠密程度选择合适的图表示方法(邻接矩阵或邻接表)也至关重要。通过对给定文件资源的分析,我们可以更深入地理解和学习这两种算法的实现和应用。

#ifndef FUNC_H_INCLUDED #define FUNC_H_INCLUDED #define MaxLNum 110 #define MaxCNum 110 #define MaxSize 10100 #define inf 10000 extern int arcs[MaxSize][MaxSize]; extern int s_nodes[MaxSize]; extern int g_nodes[MaxSize]; extern int dist[MaxSize]; extern int visited[MaxSize]; extern int pre[MaxSize]; extern int s_path[MaxSize][MaxSize]; extern int goal[MaxSize][2]; extern int s_vital[MaxSize][2]; //定义机器人(结构体)。 struct Robot{ int Pos[2]; //当前位置 char CTYPE; //当前的字符类型 struct ArEle{ char CType; int flag; }Around[8]; //周围结点的字符类型及其标记(从North开始,沿顺时针排列) }; typedef struct QNode* Queue; typedef struct Robot* PtrRt; typedef struct Node* PtrToNode; struct Node{ //队列中的结点 PtrRt Rt; PtrToNode Next; }; struct QNode { PtrToNode Front, Rear; // 队列的头、尾指针 }; Queue CreateQueue(); Queue AddQ( Queue Q, PtrRt Rt ); int IsEmpty( Queue Q ); PtrRt DeleteQ( Queue Q ); int** around(int pos[2]); int Judge(char c); void Record(PtrRt Rt,Queue Q,char expor[][MaxCNum]); PtrRt CreateRt(int x,int y,char store[][MaxCNum],int Llen,int Clen); void save_path(PtrRt Rt_1,PtrRt Rt_2,int Clen); PtrRt move(PtrRt Rt,int pos[2],char store[][MaxCNum],int Llen,int Clen); void BFS(PtrRt Rt,Queue Q,char store[][MaxCNum],char expor[][MaxCNum],int Llen,int Clen); void print_path(int path[],int u, int v,int Clen); void dijkstra(int begin,int nodes[],int Llen,int Clen); void Nicolas(char store[][MaxCNum],char expor[][MaxCNum],int Llen,int Clen); #endif // FUNC_H_INCLUDED解释代码

2023-05-30 上传

void QueryWindow::dijkstra_heap(Lgraph Graph,int s,int stime,pre *prenum,int flag) { /*堆优化Dijikstra*/ //int day = 0; int top = 0; heap node; node.dis = stime;//将起始点即编号为s的点的到达时间设为stime node.ver = s;//起始点编号为s //初始化状态数组和最小距离数组和(前驱节点和航班/列次)数组 for(int i = 0; i < Graph->Nv; i ++ ) { st[i] = false; dist[i] = INF; prenum[i].name = QString(); prenum[i].prepoint = -1; if(flag == 1 && !Graph->f_G[i].canFly) st[i] = true; } dist[s] = stime;//初始化起点的时间 push(h,top,node);//将起点入堆 while(top){ auto x = pop(h,top);//取出堆顶元素 int ver = x.ver; if(st[ver]) continue;//如果已经被选中就不再选了 st[ver] = true;//不然就选它 AdjVNode i = new adjVNode; int distance = 0; if(flag == 1){//飞机还是火车 //添加等待时间 distance = x.dis + wait_time; if(ver == s) distance -= wait_time; i = Graph->f_G[ver].First;//确定初边 }else{ distance = x.dis + wait_time2; if(ver == s) distance -= wait_time2; i = Graph->t_G[ver].First; } for( ; i ; i = i->next) { int j = i->adjv; int current_time = distance % 24;//现在的时间对应几点 int wait = (i->weight.go - current_time + 24) % 24;//如果选择这个航班/火车,需要等待的时间 if(dist[j] > distance + wait + i->weight.time) { dist[j] = distance + wait + i->weight.time; node.dis = dist[j]; node.ver = j; prenum[j].prepoint = ver; prenum[j].name = i->weight.name; push(h,top,node);//会重复入堆,还可以优化 } } } }转化成伪代码

2023-06-02 上传