C++实现Dijkstra算法的示例代码

目录
  • 一、算法原理
  • 二、具体代码
    • 1.graph类
    • 2.PathFinder类
    • 3. main.cpp
  • 三、示例

一、算法原理

链接: Dijkstra算法及其C++实现参考这篇文章

二、具体代码

1.graph类

graph类用于邻接表建立和保存有向图。

graph.h:

#ifndef GRAPH_H
#define GRAPH_H

#include <iostream>
#include <string>
#include <vector>
#include <stdlib.h>

using namespace std;

// 定义顶点
typedef struct EdgeNode {
	int adjvex;	// 顶点下标
	struct  EdgeNode *next;	// 下一条边的指针
	double cost;	// 当前边的代价

	EdgeNode();
	~EdgeNode();
} EdgeNode;

// 定义顶点表
typedef struct VexList
{
	string Vexs;  //用来存储顶点信息
	EdgeNode *firstedge;  //用来存储当前顶点的下一个顶点

	VexList();
	~VexList();
} VertexList;

// 定义图
typedef class GraphList {
public:
	GraphList();
	~GraphList();

	void PrintGraph();	// 打印图
	void CreateGraph();	// 构建图

	vector<VexList> VexList;
	int Vertexs, Edges;

} GraphList;

typedef GraphList* GraphListPtr;

#endif

graph.cpp

#include <graph.h>

EdgeNode::EdgeNode() {
	cost = 0;
	next = nullptr;
}
EdgeNode::~EdgeNode() {
	//cout << "delete Node" << endl;
}

VexList::VexList() {
	firstedge = nullptr;
}
VexList::~VexList() {
	//cout << "delete VexList" << endl;
}

GraphList::GraphList() {
	VexList.clear();
}

GraphList::~GraphList() {
	//cout << "delete GraphList" << endl;
}

void GraphList::PrintGraph() {
	cout << "所建立的地图如以下所示:" << endl;
	for (int i = 0; i< Vertexs; i++) {
		cout << VexList[i].Vexs;             //先输出顶点信息
		EdgeNode * e = VexList[i].firstedge;
		while (e) {                           //然后就开始遍历输出每个边表所存储的邻接点的下标
			if (e->cost == -1) {
				cout << "---->" << e->adjvex;
			}
			else {
				cout << "-- " << e->cost << " -->" << e->adjvex;
			}
			e = e->next;
		}
		cout << endl;
	}
}

void GraphList::CreateGraph() {
	EdgeNode *e = new EdgeNode();
	cout << "请输入顶点数和边数:" << endl;
	cin >> Vertexs >> Edges;
	cout << "请输入顶点的信息:" << endl;

	for (int i = 0; i <Vertexs; ++i) {
		VertexList tmp;
		cin >> tmp.Vexs;
		tmp.firstedge = NULL;
		VexList.push_back(tmp);
	}

	for (int k = 0; k < Edges; ++k) {
		int i, j;	//(Vi,Vj)
		double cost;
		cout << "请输入边(Vi,Vj)与 cost:" << endl;
		cin >> i >> j >> cost;
		if (VexList[i].firstedge == NULL) {//当前顶点i后面没有顶点
			e = new EdgeNode;
			e->adjvex = j;
			e->cost = cost;
			e->next = NULL;
			VexList[i].firstedge = e;
		}
		else {  //当前i后面有顶点
			EdgeNode *p = VexList[i].firstedge;
			while (p->next) {
				p = p->next;
			}
			e = new EdgeNode;
			e->adjvex = j;
			e->cost = cost;
			e->next = NULL;
			p->next = e;
		}
	}
}

2.PathFinder类

PathFinder类用于搜索最短路径

pathFinder.h

#ifndef PATH_FINDER_H
#define PATH_FINDER_H

#include <iostream>
#include <graph.h>
#include <queue>

enum State{OPEN = 0, CLOSED, UNFIND};
// 定义dijkstra求解器
class DijNode {

public:
	DijNode();
	DijNode(double _val);
	~DijNode() {};
	double getCost() { return m_cost; }
	State getState() { return m_state; }
	void setCost(double _val) { m_cost = _val; }
	void setState(State _state) { m_state = _state; }
	int getIndex() { return m_index; }
	void setIndex(int _idx) { m_index = _idx; }
	void setPred(DijNode* _ptr) { preNode = _ptr; }
	DijNode* getPred() { return preNode; }

	VertexList Vertex;
private:
	int m_index;
	double m_cost;	// 起点到当前点的代价
	State m_state;
	DijNode* preNode;	// 保存父节点
};

typedef DijNode* DijNodePtr;

// 构造优先队列用的
struct cmp {
	bool operator() (DijNodePtr &a, DijNodePtr &b) {
		return a->getCost() > b->getCost();
	}
};

class PathFinder {
public:
	priority_queue<DijNodePtr, vector<DijNodePtr>, cmp > openList;//用优先队列做openList,队首元素为最小值
	vector<DijNodePtr> m_path;	// 存放最终路径
	PathFinder() {
		openList.empty();
		m_path.clear();
	}
	~PathFinder() {};

	void StoreGraph(GraphListPtr _graph);
	void Search(int start, int end);
	void retrievePath(DijNodePtr _ptr);

	vector<DijNodePtr> NodeList;

private:
	GraphListPtr m_graph;
	/*vector<DijNodePtr> NodeList;*/
};

typedef PathFinder* PathFinderPtr;
#endif

PathFinder.cpp

#include <PathFinder.h>

DijNode::DijNode() {
	m_cost = -1;	// -1表示未被探索过,距离为无穷,非负数表示已经被探索过
	m_index = -1;
	m_state = UNFIND;	// OPEN表示openlist, CLOSED表示在closeList中,UNFIND表示未探索过
	preNode = nullptr;
}

DijNode::DijNode(double _val) {
	m_cost = _val;	// -1表示未被探索过,非负数表示已经被探索过
	m_index = -1;
	m_state = UNFIND;	// OPEN表示openlist, CLOSED表示在closeList中,UNFIND表示未探索过
	preNode = nullptr;
}

void PathFinder::StoreGraph(GraphListPtr _graph) {
	for (int i = 0; i < _graph->VexList.size(); ++i) {
		DijNodePtr node = new DijNode();
		node->Vertex = _graph->VexList[i];
		node->setIndex(i);
		NodeList.push_back(node);
	}
}

void PathFinder::Search(int start, int end) {
	// 搜索起点
	DijNodePtr m_start = NodeList[start];
	m_start->setCost(0);
	m_start->setIndex(start);
	m_start->setState(OPEN);
	openList.push(m_start);

	int count = 0;
	while (!openList.empty()) {

		// 弹出openList中的队首元素
		DijNodePtr cur = openList.top();
		cur->setState(CLOSED);	// 加入closelist中
		openList.pop();

		// 遍历队首元素所有的边
		EdgeNode *e = cur->Vertex.firstedge;
		while (e != nullptr) {
			int _index = e->adjvex;
			double _cost = e->cost;

			//cout << "_cost = " << _cost << endl;
			// 如果节点在close list中,直接跳过
			if (NodeList[_index]->getState() == CLOSED) {
				continue;
			}

			if (NodeList[_index]->getCost() == -1) {
				NodeList[_index]->setCost(cur->getCost() + _cost);	// 更新代价
				NodeList[_index]->setPred(cur);		// 更新父节点
				NodeList[_index]->setState(OPEN);	// 加入open list中
				openList.push(NodeList[_index]);
			}
			else if (cur->getCost() + _cost < NodeList[_index]->getCost()) {
				// 如果从当前节点到第_index个节点的距离更短,更新距离和父节点
				NodeList[_index]->setCost(cur->getCost() + _cost);	// 更新代价
				NodeList[_index]->setPred(cur);		// 更新父节点
				NodeList[_index]->setState(OPEN);	// 加入open list中
			}

			e = e->next;
		}
	}

	cout << "最短距离为:" << NodeList[end]->getCost() << endl;
	retrievePath(NodeList[end]);

}

void PathFinder::retrievePath(DijNodePtr ptr) {
	while (ptr != nullptr) {
		m_path.push_back(ptr);
		ptr = ptr->getPred();
	}
	reverse(m_path.begin(),m_path.end());
}

3. main.cpp

主函数

#include <graph.h>
#include <PathFinder.h>

int main() {
	cout << "构建地图" << endl;
	GraphListPtr graph = new GraphList();
	graph->CreateGraph();

	cout << "\n \n";
	graph->PrintGraph();

	PathFinderPtr _solver = new PathFinder();
	_solver->StoreGraph(graph);

	cout << "\n \n";

	int start, end;
	cout << "输入起点" << endl;
	cin >> start;

	cout << "输入终点" << endl;
	cin >> end;

	cout << "\n \n";

	_solver->Search(start, end);
	cout << "最短路径为:";

	for (int i = 0; i < _solver->m_path.size(); ++i) {
		 cout << _solver->m_path[i]->Vertex.Vexs ;
		 if (i < _solver->m_path.size() - 1)
			 cout << "-->";
	}
	cout << endl;

	system("pause");
	return 0;
}

三、示例

以上就是C++实现Dijkstra算法的示例代码的详细内容,更多关于C++ Dijkstra算法的资料请关注我们其它相关文章!

(0)

相关推荐

  • Dijkstra算法最短路径的C++实现与输出路径

    某个源点到其余各顶点的最短路径 这个算法最开始心里怕怕的,不知道为什么,花了好长时间弄懂了,也写了一遍,又遇到时还是出错了,今天再次写它,心里没那么怕了,耐心研究,懂了之后会好开心的,哈哈 Dijkstra算法: 图G 如图:若要求从顶点1到其余各顶点的最短路径,该咋求: 迪杰斯特拉提出"按最短路径长度递增的次序"产生最短路径. 首先,在所有的这些最短路径中,长度最短的这条路径必定只有一条弧,且它的权值是从源点出发的所有弧上权的最小值,例如:在图G中,从源点1出发有3条弧,其中以弧(1

  • C++实现Dijkstra(迪杰斯特拉)算法

    Dijkstra算法 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,是广度优先算法的一种,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.其基本原理是:每次新扩展一个距离最短的点,更新与其相邻的点的距离.当所有边权都为正时,由于不会存在一个距离更短的没扩展过的点,所以这个点的距离永远不会再被改变,因而保证了算法的正确性.不过根据这个原理,用Dijkstra求最短路的图不能有负权边,因为扩展到负权边的时候会产生更短的距离,有可能就破

  • C++ Dijkstra算法之求图中任意两顶点的最短路径

    Dijkstra算法是图中找任意两点中最短路径的一种经典算法. 重点的步骤总结如下: 1.算法采用了并查集 (之后都叫它为 最短路径顶点集 ):即每次都找离开始顶点距离最短的顶点,然后把该顶点加入最短路径顶点集中(已经加入最短路径顶点集里的那些顶点 下一次就会跳过它了,并且,在顶点集里 任意两个顶点间的距离 都已经是最短) 2.用来记录从源点(开始顶点) 到vi (0<=i<=numVertices) 的最短距离 的数组dist[numVertices] ,并且这个数组的元素值是会不断变化的,

  • C++实现Dijkstra算法

    本文实例为大家分享了C++实现Dijkstra算法的具体代码,供大家参考,具体内容如下 #include <iostream> #include <limits> using namespace std; struct Node { //定义表结点 int adjvex; //该边所指向的顶点的位置 int weight;// 边的权值 Node *next; //下一条边的指针 }; struct HeadNode{ // 定义头结点 int nodeName; // 顶点信息

  • C++用Dijkstra(迪杰斯特拉)算法求最短路径

    算法介绍 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低. 算法思想 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的集合(初始时只含有源点V0) (2)V-S=T:尚未确定的顶点集合 将T中顶点按递增

  • C++求所有顶点之间的最短路径(用Dijkstra算法)

    本文实例为大家分享了C++求所有顶点之间最短路径的具体代码,供大家参考,具体内容如下 一.思路: 不能出现负权值的边 (1)轮流以每一个顶点为源点,重复执行Dijkstra算法n次,就可以求得每一对顶点之间的最短路径及最短路径长度,总的执行时间为O(n的3次方) (2)另一种方法:用Floyd算法,总的执行时间为O(n的3次方)(另一文章会写) 二.实现程序: 1.Graph.h:有向图 #ifndef Graph_h #define Graph_h #include <iostream> u

  • C++简单实现Dijkstra算法

    本文实例为大家分享了C++简单实现Dijkstra算法的具体代码,供大家参考,具体内容如下 // Dijkstra.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include <stack> #define MAX_VALUE 1000 using namespace std; struct MGraph { int *edges[MAX_VALUE]; int iVertex

  • Java实现Dijkstra算法的示例代码

    目录 一 问题描述 二 实现 三 测试 一 问题描述 小明为位置1,求他到其他各顶点的距离. 二 实现 package graph.dijkstra; import java.util.Scanner; import java.util.Stack; public class Dijkstra { static final int MaxVnum = 100; // 顶点数最大值 static final int INF = 0x3f3f3f3f; //无穷大 static final int

  • C++实现Dijkstra算法的示例代码

    目录 一.算法原理 二.具体代码 1.graph类 2.PathFinder类 3. main.cpp 三.示例 一.算法原理 链接: Dijkstra算法及其C++实现参考这篇文章 二.具体代码 1.graph类 graph类用于邻接表建立和保存有向图. graph.h: #ifndef GRAPH_H #define GRAPH_H #include <iostream> #include <string> #include <vector> #include &l

  • Java实现8种排序算法的示例代码

    冒泡排序 O(n2) 两个数比较大小,较大的数下沉,较小的数冒起来. public static void bubbleSort(int[] a) { //临时变量 int temp; //i是循环次数,也是冒泡的结果位置下标,5个数组循环5次 for (int i = 0; i < a.length; i++) { //从最后向前面两两对比,j是比较中下标大的值 for (int j = a.length - 1; j > i; j--) { //让小的数字排在前面 if (a[j] <

  • JAVA用递归实现全排列算法的示例代码

    求一个n阶行列式,一个比较简单的方法就是使用全排列的方法,那么简述以下全排列算法的递归实现. 首先举一个简单的例子说明算法的原理,既然是递归,首先说明一下出口条件.以[1, 2]为例 首先展示一下主要代码(完整代码在后面),然后简述 //对数组array从索引为start到最后的元素进行全排列 public void perm(int[]array,int start) { if(start==array.length) { //出口条件 for(int i=0;i<array.length;i

  • c# 实现KMP算法的示例代码

    KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特-莫里斯-普拉特操作(简称KMP算法).KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息.KMP算法的时间复杂度O(m+n) . 实现方式就不再这里献丑了,网上很多讲解,此处只是记录下c#实现的代码. public class KMP { public

  • python实现经典排序算法的示例代码

    以下排序算法最终结果都默认为升序排列,实现简单,没有考虑特殊情况,实现仅表达了算法的基本思想. 冒泡排序 内层循环中相邻的元素被依次比较,内层循环第一次结束后会将最大的元素移到序列最右边,第二次结束后会将次大的元素移到最大元素的左边,每次内层循环结束都会将一个元素排好序. def bubble_sort(arr): length = len(arr) for i in range(length): for j in range(length - i - 1): if arr[j] > arr[j

  • Python实现七大查找算法的示例代码

    查找算法 -- 简介 查找(Searching)就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素.     查找表(Search Table):由同一类型的数据元素构成的集合     关键字(Key):数据元素中某个数据项的值,又称为键值     主键(Primary Key):可唯一的标识某个数据元素或记录的关键字 查找表按照操作方式可分为:         1.静态查找表(Static Search Table):只做查找操作的查找表.它的主要操作是:         ①

  • C#实现一阶卡尔曼滤波算法的示例代码

    //FilterKalman.cs namespace FusionFiltering { public class FilterKalman { private double A = 1; private double B = 0; private double H = 1; private double R; private double Q; private double cov = double.NaN; private double x = double.NaN; public Fil

  • Java实现查找算法的示例代码(二分查找、插值查找、斐波那契查找)

    目录 1.查找概述 2.顺序查找 3.二分查找 3.1 二分查找概述 3.2 二分查找实现 4.插值查找 4.1 插值查找概述 4.2 插值查找实现 5.斐波那契查找 5.1 斐波那契查找概述 5.2 斐波那契查找实现 5.3 总结 1.查找概述 查找表: 所有需要被查的数据所在的集合,我们给它一个统称叫查找表.查找表(Search Table)是由同一类型的数据元素(或记录)构成的集合. 查找(Searching): 根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录).

  • Python和Matlab实现蝙蝠算法的示例代码

    目录 1前言 2 蝙蝠算法原理细讲 3 详细步骤 4Python实现 4.1代码 4.2结果 5Matlab实现 5.1 代码 5.2 结果 5.3 展望 1 前言 蝙蝠算法是2010年杨教授基于群体智能提出的启发式搜索算法,是一种搜索全局最优解的有效方法.该算法基于迭代优化,初始化为一组随机解,然后迭代搜寻最优解,且在最优解周围通过随机飞行产生局部新解,加强局部搜索速度.该算法具有实现简单.参数少等特点. 该算法主要用于目标函数寻优,基于蝙蝠种群利用产生的声波搜索猎物和控制飞行方向的特征来实现

随机推荐