数据结构_图_最短路径_狄杰斯特拉(Dijkstra)算法

数据结构_图_最短路径_狄杰斯特拉(Dijkstra)算法

此算法没有采用《数据结构C语言版》中的存储结构,而是采用邻接表的方法存储图,经过改进,还能输出最短路径。

Dijkstra.h

#include<iostream>
using namespace std;

#define MAX_VEX_NUM 20
#define INFINITY INT_MAX
#define CANTFIND -1

class Path //记录源点到每一个点的路径
{
public:
	Path();
	int pathnode;
	Path *next;
};

Path::Path()
{
	pathnode = 0;
	next = NULL;
}

class NextNode //邻接表存储以某节点为尾的弧的相关信息
{
public:
	NextNode();
	int nextvex; //顶点编号
	int weight; //弧上的权值
	NextNode *next; //下一个节点的指针
};

NextNode::NextNode()
{
	nextvex = weight = 0;
	next = NULL;
}

class VexNode //顶点相关信息
{
public:
	VexNode();
	char name; //顶点名称
	bool choose; //标示此节点标示的最短路径是否已经被选择
	int dist; //此节点当前存放的最短路径
	NextNode *firstnext;
	Path *path;
};

VexNode::VexNode()
{
	choose = false;
	dist = INFINITY;
	firstnext = NULL;
	path = NULL;
}

class VexBox //顶点集合
{
public:
	VexBox();
	int vexnum; //定点数目
	VexNode vexbox[MAX_VEX_NUM]; //顶点集合
};

VexBox::VexBox()
{
	vexnum = 0;
}

class ShortestPath_DIJ
{
public:
	void ShortestPath(); //接口函数
private:
	void GetVex(); //得到顶点信息
	void GetArc(); //得到弧的相关信息	
	void GetShortestPath(); //得到最短路径
	void PrintShortestPath(); //打印最短路径
	int GetShortestNode(); //得到dist最小的节点
	void UpdatePath(int, int); //更新路径
	void ReMove(Path*); //销毁原路径
	VexBox v; //顶点集合
	int sourse;
};

void ShortestPath_DIJ::ShortestPath()
{
	GetVex(); //得到顶点信息
	GetArc(); //得到弧的相关信息	
	GetShortestPath(); //得到最短路径
	PrintShortestPath(); //打印最短路径
}

void ShortestPath_DIJ::GetVex() //得到顶点信息
{
	cout << "Please Input The Name Of Each Vertex :" << endl << endl;
	char name;
	while (cin >> name)
	{
		v.vexbox[v.vexnum++].name = name;
	}
	cin.clear();
}

void ShortestPath_DIJ::GetArc() //得到弧的相关信息
{
	cout << "Please Input The Information Of Each Arc :" << endl
			<< "tail head weight" << endl;
	int tail, head, weight;
	NextNode *newnode, *p;
	while (cin >> tail >> head >> weight)
	{
		newnode = new NextNode;
		newnode->nextvex = head;
		newnode->weight = weight;
		if ((p = v.vexbox[tail].firstnext) == NULL)
		{
			v.vexbox[tail].firstnext = newnode;
		} //if
		else
		{
			while (p->next != NULL)
				p = p->next;
			p->next = newnode;
		} //else
	} //while
	cin.clear();
}

int ShortestPath_DIJ::GetShortestNode() //得到dist最小的节点
{
	int ans = CANTFIND, min = INT_MAX;
	for (int i = 0; i < v.vexnum; i++)
	{
		if (v.vexbox[i].choose == false && v.vexbox[i].dist < min)
		{
			min = v.vexbox[i].dist;
			ans = i;
		} //if
	} //for
	v.vexbox[ans].choose = true; //标记为已选择
	return ans;
}

void ShortestPath_DIJ::ReMove(Path *p) //销毁原路径
{
	if (p->next != NULL)
		ReMove(p->next);
	delete p;
}

void ShortestPath_DIJ::UpdatePath(int a, int b) //更新路径
{
	Path *p, *pt, *newpath;
	ReMove(v.vexbox[b].path);
	newpath = new Path;
	newpath->pathnode = v.vexbox[a].path->pathnode;
	v.vexbox[b].path = newpath;
	p = v.vexbox[a].path->next;
	pt = v.vexbox[b].path;
	while (p != NULL)
	{
		newpath = new Path;
		newpath->pathnode = p->pathnode;
		pt->next = newpath;
		p = p->next;
		pt = pt->next;
	}
}

void ShortestPath_DIJ::GetShortestPath() //得到最短路径
{
	Path *newpath, *pt;
	cout << "Please Input The Sourse :" << endl;
	while (cin >> sourse && !(sourse < v.vexnum))
		; //得到符合条件的源点
	cout << v.vexbox[sourse].name << " : Start" << endl;
	v.vexbox[sourse].dist = 0; //对源点的相关处理
	for (int i = 0; i < v.vexnum; i++) //初始化路径
	{
		if (i != sourse)
		{
			newpath = new Path;
			newpath->pathnode = sourse;
			v.vexbox[i].path = newpath;
		}
	}
	NextNode *p;
	p = v.vexbox[sourse].firstnext;
	while (p != NULL)
	{
		newpath = new Path;
		newpath->pathnode = p->nextvex;
		v.vexbox[p->nextvex].path->next = newpath;
		v.vexbox[p->nextvex].dist = p->weight;
		p = p->next;
	}
	int ncase = v.vexnum - 1;
	int node;
	while (ncase--) //处理源点到其他点的最短路径长度
	{
		node = GetShortestNode(); //获得当前情况下未被选择的最短边
		if (node == CANTFIND) //控制跳出
			break;
		p = v.vexbox[node].firstnext;
		while (p != NULL) //如有必要修改和该顶点相关的节点的Dist值
		{
			if (v.vexbox[node].dist + p->weight < v.vexbox[p->nextvex].dist)
			{
				v.vexbox[p->nextvex].dist = v.vexbox[node].dist + p->weight;
				UpdatePath(node, p->nextvex);
				newpath = new Path;
				newpath->pathnode = p->nextvex;
				pt = v.vexbox[p->nextvex].path;
				while (pt->next != NULL)
					pt = pt->next;
				pt->next = newpath;
			}
			p = p->next;
		}
	}
}

void ShortestPath_DIJ::PrintShortestPath() //打印最短路径
{
	Path *p;
	for (int i = 0; i < v.vexnum; i++)
	{
		if (i != sourse)
		{
			p = v.vexbox[i].path;
			cout << v.vexbox[i].name << " : ";
			if (v.vexbox[i].dist == INFINITY)
				cout << "∞" << endl;
			else
			{
				cout << v.vexbox[i].dist << " Path :"; //打印路径
				cout << v.vexbox[p->pathnode].name;
				p = p->next;
				while (p != NULL)
				{
					cout << "->" << v.vexbox[p->pathnode].name;
					p = p->next;
				}
				cout << endl;
			}
		} //if
	} //for
}

main.cpp

#include"Dijkstra.h"
 
int main()
{
	ShortestPath_DIJ d;
	d.ShortestPath();
	system("pause");
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注