一个稍微特殊点的地方就是 min() 函数,考虑到要面对 Infinity 的情况,作乐多种检查来应对.
不仅可以计算出每对顶点间得最短路径,还支持打印路径.看书学,自己又一顿琢磨.懵的也好,会的也好,是睾出来了.下次再遇到这个问题,最起码的,知道有一种方法可以解决,哪怕不能立刻写出来.好像,也很难做到写过一次就记得住,对我来说.
// graphRepresentAsAdjacentMatrix.cpp -- implement file.
// 2011-09-16-18.07 -- 2011-09-16-19.42 by Golden_Shadow.
// 2011-09-17-09.39 -- 2011-09-17-12.00 by Golden_Shadow.
#include "stdafx.h"
#include "graphRepresentAsAdjacentMatrix.h"
// private methods of class Graph:
// ---------------------
int Graph ::m_min (int a, int partAOfB, int partBOfB)
{
if (Infinity == (partAOfB & partBOfB))
{
// Both partAOfB and partBOfB are Infinity.
// Return a, even through a is Infinity.
return a ;
}
else if (Infinity == a)
{
// Only a is Infinity
if (partAOfB != Infinity && partBOfB != Infinity)
{
// Neither partAOfB nor partBOfB is Infinity.
return partAOfB + partBOfB ;
}
else
{
// Either both partAOfB and partBOfB are Infinity or one of them is Infinity.
return Infinity ;
}
}
else
{
return a < partAOfB + partBOfB ? a : partAOfB + partBOfB ;
}
}
// ---------------------
// public methods of class Graph:
// ---------------------
// Assume m_rows > 0
Graph ::Graph (unsigned int rows): m_rows(rows), m_currentRows(0)
{
m_matrix = new int*[m_rows] ;
for (int i = 0; i < m_rows; ++i)
{
m_matrix[i] = new int[m_rows] ;
}
m_distance = new int*[m_rows] ;
for (int i = 0; i < m_rows; ++i)
{
m_distance[i] = new int[m_rows] ;
}
for (int i = 0; i != m_rows; ++i)
{
for (int j = 0; j != m_rows; ++j)
{
m_matrix[i][j] = Infinity ;
}
}
m_parent = new int*[m_rows] ;
for (int i = 0; i < m_rows; ++i)
{
m_parent[i] = new int[m_rows] ;
}
for (int i = 0; i != m_rows; ++i)
{
for (int j = 0; j != m_rows; ++j)
{
m_parent[i][j] = Nil ;
}
}
}
// ---------------------
// ---------------------
bool Graph ::importARowOfGraph (const std ::vector<int> & indexOfCurrentVertexAdjoinTo, const std ::vector<int> & weightOfCurrentVertexAdjoinTo)
{
if (m_currentRows >= m_rows)
return false ;
if (indexOfCurrentVertexAdjoinTo.size() != weightOfCurrentVertexAdjoinTo.size())
return false ;
std ::vector<int> ::const_iterator indexIter = indexOfCurrentVertexAdjoinTo.begin() ;
std ::vector<int> ::const_iterator weightIter = weightOfCurrentVertexAdjoinTo.begin() ;
while (indexIter != indexOfCurrentVertexAdjoinTo.end())
{
m_matrix[m_currentRows][*indexIter] = *weightIter ;
++indexIter ;
++weightIter ;
}
m_matrix[m_currentRows][m_currentRows] = 0 ;
++m_currentRows ;
return true ;
}
// ---------------------
// ---------------------
void Graph ::floydWarshall (void)
{
if (m_currentRows != m_rows)
return ;
// Initialize m_distance as m_matrix.
for (int i = 0; i < m_rows; ++i)
{
for (int j = 0; j < m_rows; ++j)
{
m_distance[i][j] = m_matrix[i][j] ;
}
}
// Initialize m_parent as m_matrix.
for (int i = 0; i < m_rows; ++i)
{
for (int j = 0; j < m_rows; ++j)
{
if (i != j && m_matrix[i][j] != Infinity)
{
m_parent[i][j] = i ;
}
}
}
for (int k = 0; k != m_rows; ++k)
{
for (int i = 0; i != m_rows; ++i)
{
for (int j = 0; j != m_rows; ++j)
{
Weight temp = m_distance[i][j] ;
m_distance[i][j] = m_min(m_distance[i][j], m_distance[i][k], m_distance[k][j]) ;
if (m_distance[i][j] < temp)
{
m_parent[i][j] = m_parent[k][j] ;
}
}
}
}
}
// ---------------------
// ---------------------
// Assume both startVertex and endVertex are in the range [0, |V|).
void Graph ::printPathBetweenTwoVertexes (int startVertex, int endVertex)
{
if (startVertex != endVertex)
{
printPathBetweenTwoVertexes(startVertex, m_parent[startVertex][endVertex]) ;
std ::cout << "-> V[" << endVertex << "]" ;
}
else
std ::cout << "V[" << startVertex << "]" ;
}
// ---------------------
// ---------------------
Graph ::~Graph (void)
{
for (int i = 0; i < m_rows; ++i)
{
delete []m_matrix[i] ;
}
delete []m_matrix ;
for (int i = 0; i < m_rows; ++i)
{
delete []m_distance[i] ;
}
delete []m_distance ;
for (int i = 0; i < m_rows; ++i)
{
delete []m_parent[i] ;
}
delete []m_parent ;
}
// ---------------------