《数据结构实战》------------------------------------实现Dijkstra算法

下面该代码是对dijkstra算法的实现:

#ifndef __CDIJKSTRA__H
#define __CDIJKSTRA__H

#include <iostream>
#include <string>
#include <vector>

//dijkstra 算法 仅针无负权有向图

const int NERVER_ATTACH = 9999;

struct AdjacencyNode // 邻接点 含加权
{
	struct VertexNode* pNode;
	int nWeight; // 加权值
};

struct VertexNode // 顶点
{
	std::string cName; // 顶点名字
	int  nInDegree; // 入度
	int  nDistance; // 最短路径
	std::vector<struct AdjacencyNode> vectNodes; // 邻接点
	VertexNode()
	{
		cName = "";
		nInDegree = NERVER_ATTACH; // 未分配的顶点
		nDistance = NERVER_ATTACH;
		vectNodes.clear();
	}
};

class CDijkstra
{
public:
	CDijkstra(int nNodes);
	~CDijkstra();

public:
	bool InsertEdge(std::string aIn, std::string bOut, int nWeight); // 插入有向边 aIn-->aOut 及加权
	void Dijkstra(std::string sVertex); // 查找顶点strNode到所有顶点的最短路径
private:
	void FindIndexInsert(std::string aIn, int& nInsertIndex, bool& bFindInsert, bool& bFindIn);
private:
	struct VertexNode* m_pNodes; // 所有顶点的集合
	int    m_nNodes; // 顶点数量
};


#endif

#include "Dijkstra.h"
#include <queue>

CDijkstra::CDijkstra(int nNodes) : m_nNodes(nNodes)
{
	m_pNodes = new struct VertexNode[nNodes];
}


CDijkstra::~CDijkstra()
{
	delete[] m_pNodes;
}

void CDijkstra::FindIndexInsert(std::string aIn, int& nInsertIndex, bool& bFindInsert, bool& bFindIn)
{
	nInsertIndex = 0;
	bFindInsert = false;
	bFindIn = false;
	for (int i = 0; i < m_nNodes; i++)
	{
		if ((m_pNodes + i)->cName != aIn && (m_pNodes + i)->nInDegree == NERVER_ATTACH && !bFindInsert)
		{
			nInsertIndex = i;
			bFindInsert = true;
		}
		if ((m_pNodes + i)->cName == aIn)
		{
			bFindIn = true;
			nInsertIndex = i;
			break;
		}
	}
}

bool CDijkstra::InsertEdge(std::string aIn, std::string bOut, int nWeight)
{
	int nInsertIndex = 0;
	bool bFindInsert = false;
	bool bFindIn = false;
	int nInsertIndexOut = 0;
	bool bFindInsertOut = false;
	bool bFindInOut = false;
	FindIndexInsert(aIn, nInsertIndex, bFindInsert, bFindIn);
	if (bFindInsert && !bFindIn) // 还未分配
	{
		(m_pNodes + nInsertIndex)->cName = aIn;
		(m_pNodes + nInsertIndex)->nInDegree = 0; // 入度为0
	}
	FindIndexInsert(bOut, nInsertIndexOut, bFindInsertOut, bFindInOut);
	if (bFindInsertOut && !bFindInOut) // 还未分配
	{
		(m_pNodes + nInsertIndexOut)->cName = bOut;
		(m_pNodes + nInsertIndexOut)->nInDegree = 0; // 入度为0
	}
	(m_pNodes + nInsertIndexOut)->nInDegree += 1; // 入度加1
	struct AdjacencyNode objNode;
	objNode.nWeight = nWeight;
	objNode.pNode = m_pNodes + nInsertIndexOut;
	(m_pNodes + nInsertIndex)->vectNodes.push_back(objNode); // 改变邻接表
	return true;
}

void CDijkstra::Dijkstra(std::string sVertex)
{
	int nInsertIndex = 0;
	bool bFindInsert = false;
	bool bFindIn = false;
	FindIndexInsert(sVertex, nInsertIndex, bFindInsert, bFindIn);
	if (!bFindIn) // 没有该顶点
		return;
	for (int i = 0; i < m_nNodes; i++) // 初始化到所有顶点的路径长度
		(m_pNodes + i)->nDistance = NERVER_ATTACH; //unknow
	(m_pNodes + nInsertIndex)->nDistance = 0; // 自己到自己的路径为0
	std::queue<struct VertexNode*> queueNode;
	queueNode.push(m_pNodes + nInsertIndex);
	while (!queueNode.empty())
	{
		VertexNode* pNode = queueNode.front();
		queueNode.pop();
		if (!pNode->vectNodes.empty()) // 是否有邻接点
		{
			for (auto iter = pNode->vectNodes.begin(); iter != pNode->vectNodes.end(); iter++)
			{
				if (iter->pNode->nDistance == NERVER_ATTACH) // 更新
				{
					iter->pNode->nDistance = pNode->nDistance + iter->nWeight;
					queueNode.push(iter->pNode);
				}
				else if (iter->nWeight + pNode->nDistance < iter->pNode->nDistance)
				{
					iter->pNode->nDistance = iter->nWeight + pNode->nDistance;
					queueNode.push(iter->pNode);
				}
			}
		}
	}

	// 打印最短路径
	for (int i = 0; i < m_nNodes; i++)
	{
		std::cout << sVertex << " 到顶点" << (m_pNodes + i)->cName << "的最短距离为: ";
		if ((m_pNodes + i)->nDistance == NERVER_ATTACH)
			std::cout << "无法到达" << std::endl;
		else
			std::cout << (m_pNodes + i)->nDistance << std::endl;
	}
}

#include "Dijkstra.h"

int main()
{
	CDijkstra objDijstra(7);
	objDijstra.InsertEdge("v1", "v2", 2);
	objDijstra.InsertEdge("v1", "v4", 1);
	objDijstra.InsertEdge("v2", "v4", 3);
	objDijstra.InsertEdge("v2", "v5", 10);
	objDijstra.InsertEdge("v3", "v6", 5);
	objDijstra.InsertEdge("v3", "v1", 4);
	objDijstra.InsertEdge("v4", "v3", 2);
	objDijstra.InsertEdge("v4", "v5", 2);
	objDijstra.InsertEdge("v4", "v6", 8);
	objDijstra.InsertEdge("v4", "v7", 4);
	objDijstra.InsertEdge("v5", "v7", 6);
	objDijstra.InsertEdge("v7", "v6", 1);

	objDijstra.Dijkstra("v1");
	std::cin.get();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值