DAG,Dijkstra,Bellmen-Ford之间的原理,异同,应用

DAG(有向无环图)、Dijkstra算法和Bellman-Ford算法都是图论中的重要概念和算法。它们各自有不同的原理、应用场景和特点。以下是它们之间的异同和应用。

1. DAG(有向无环图)

原理

  • DAG是一种有向图,其中不存在从某个顶点出发又能回到该顶点的路径(即没有环路)。
  • DAG的一个重要特性是可以进行拓扑排序。

应用

  • 任务调度:表示任务之间的依赖关系。
  • 数据处理流程:如编译器中的表达式树。
  • 确定性模型:如版本控制系统中的提交历史。

2. Dijkstra算法

原理

  • Dijkstra算法用于计算从单个源点到所有其他顶点的最短路径。
  • 适用于边权非负的图。
  • 算法使用贪心策略,逐步扩展已知的最短路径。

应用

  • 地图导航系统:寻找最短路径。
  • 网络路由协议:如OSPF(开放最短路径优先)。
  • 交通优化:实时交通流量分析。
  • Dijkstra算法求最短路径:
    • 测试用例:
    • 预期结果:
核心代码如下:
void Graph::dijkstra(int startId)
{//先把它从队列中删除,然后找到它的邻居顶点并更新节点的值直到队列为空
	Pritree<Vertex> pritree;
	initialForDij(pritree, startId);
	while(pritree.getSize() != 0)
	{
			Vertex temp =  pritree.popHead();//找到discovery最小的值
			Vertex* vertexp = findVerAccId(temp.getVertexId());
			Node* neighbor = vertexp->getHeadNode();//找到邻居节点
		//	cout<<temp.getVertexId()<<"->  ";
			while(neighbor != NULL)//对每一个邻居节点进行循环中的操作
			{
				Vertex* tempNe = neighbor->getVertex();//与弹出来的顶点相邻的顶点
				if(tempNe->getDiscovery() > temp.getDiscovery() + neighbor->getWeight())
				{
					tempNe->setDiscovery(temp.getDiscovery() + neighbor->getWeight());
					tempNe->setParent(vertexp);//记住其父节点
					pritree.delete_ele(*tempNe, equal);//从优先队列中删除
					pritree.insert(*tempNe);//然后插入新的更新后的顶点
				}
				neighbor = neighbor->getNextNode();
			}
	}
//打印出最后的结果
	Vertex* for_out_ver = this->headVertex;
	cout<<"dijkstra:"<<endl;
	while(for_out_ver != NULL)
	{
		for_out_ver = for_out_ver->getNextVertex();
		if(for_out_ver != NULL)
		  cout<<(for_out_ver->getParent())->getVertexId()<<"->"<<for_out_ver->getVertexId()<<endl;
	}

}

3. Bellman-Ford算法

原理

  • Bellman-Ford算法也用于计算从单个源点到所有其他顶点的最短路径。
  • 可以处理边权为负的图,并能检测负权环。
  • 通过动态规划的方式,逐步更新路径长度。

应用

  • 适用于存在负权边的图,如金融网络中的套利检测。
  • 网络路由协议:如RIP(路由信息协议)。
  • 解决最短路径问题的更一般化场景。
  • Bellman-Ford算法求最短路径:
    • 测试用例:
    • 预期结果:
  核心代码如下:
void Graph::bellmanFord(int startId)
{
	//初始化
	Vertex* vptr = this->headVertex;
	while(vptr != NULL)
	{
		if(vptr->getVertexId() == startId)
			vptr->setDiscovery(0);
		else
			vptr->setDiscovery(INT_MAX);

		vptr->setParent(NULL);
		vptr = vptr->getNextVertex();
	}

	//最外层迭代顶点数目减一次
	for(int counter0 = 1; counter0 < this->vertexNumber; counter0++)
	{
		vptr = this->headVertex;
		while(vptr != NULL)//遍历每一个顶点
		{
			Node* eptr = vptr->getHeadNode();
			while(eptr != NULL)//遍历每一条边
			{
				Vertex* vtoptr = eptr->getVertex();
				if( vtoptr->getDiscovery()> vptr->getDiscovery()+eptr->getWeight())
				{
					vtoptr->setDiscovery(vptr->getDiscovery()+eptr->getWeight());
					vtoptr->setParent(vptr);
				}
				eptr = eptr->getNextNode();
			}
			vptr = vptr->getNextVertex();
		}
	}

	Vertex* for_out_ver = this->headVertex;
	cout<<"bellman-ford:"<<endl;
	while(for_out_ver != NULL)
	{
		for_out_ver = for_out_ver->getNextVertex();
		if(for_out_ver != NULL)
			cout<<(for_out_ver->getParent())->getVertexId()<<"->"<<for_out_ver->getVertexId()<<endl;
	}

}

4.异同点总结

特性DAGDijkstra算法Bellman-Ford算法
图的类型有向无环图有向图(非负边权)有向图(可包含负边权)
算法性质拓扑排序贪心算法动态规划
负权边处理不适用不适用支持
适用场景任务调度、数据流程最短路径查找负权检测、一般最短路径查找

总结

  • DAG用于表示无环的依赖关系,适合任务调度等场景。
  • Dijkstra算法适合处理边权非负的最短路径问题,常用于实时导航。
  • Bellman-Ford算法则适合处理更复杂的图形,尤其是需要处理负权边的情况,能够检测负权环
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值