好一段时间前写的了。。。正好现在在复习数据结构,重构了一下代码
首先先是 图、点Vertex和边AdjACent的定义
class JpGraph
{
public:
class Vertex;
class AdjAcent
{
public:
int cost;
Vertex* ptr;
explicit AdjAcent(int newCost = 0,Vertex* newPtr = nullptr):cost(newCost),ptr(newPtr){}
};
class Vertex
{
public:
int index;
int inDegree;
vector degree;
Vertex(int data, int in_degree)
: index(data),
inDegree(in_degree)
{
}
};
JpGraph(){}
void lowestCost(const Vertex& v);
void buildGraph(vector vertexs);
void BFS(int index);
void DFS(int index);
void topSort();
private:
vector vertexs;
};
下面是最短路径的实现,也就是dijkstra算法的实现
inline void JpGraph::lowestCost(const Vertex& v) //形参既是从哪个点开始算
{
vectorbool , int>> status;
for (int i = 0; i < vertexs.size(); ++i)
{
status.push_back(pair<bool, int>(false, INT32_MAX));
}
//建立与相应点集对应的集合。
status[v.index].second = 0;
auto findMin = [&]() //lambda表达式,反正我就这个函数用就没单独写个私有函数
//目的是找到当前权重最小的点的下标
{
int min = INT32_MAX;
int minIndx = 0;
for (int i = 0; i < status.size(); ++i)
if (status[i].second < min && status[i].first == false)
{
min = status[i].second;
minIndx = i;
}
return minIndx;
};
auto isAllTrue = [&]() //检查所有的点是不是都已标记为true
{
for (const auto& i : status)
{
if (i.first == false)
return false;
}
return true;
};
//以前写的实现,这次重构发现完全没必要全部遍历。。dijkstra算法的思想可不就是贪心么。。不知道以前咋想的
//for (;;)
//{
// status[findMin()].first = true; //每次都将未知的点集中的最小值设为已知
// for (int i = 0; i < status.size(); ++i)
// {
// if (status[i].first == true)
// {
// for (const auto& adj : vertexs[i].degree)
// {
// auto desV = (*(adj.ptr)).index;
// if (status[i].second + adj.cost < status[desV].second) //对与已知点相连接的点的cost进行更新
// status[desV].second = status[i].second + adj.cost;
// }
// }
// }
// if (isAllTrue()) //如果所有点都已知,则退出循环
// break;
//}
while(!isAllTrue())
{
auto minIndex = findMin();
status[minIndex].first = true; //每次都将未知的点集中的最小值设为已知
for (const auto& adj : vertexs[minIndex].degree)
{
auto desV = (*(adj.ptr)).index;
if (status[minIndex].second + adj.cost < status[desV].second) //对与已知点相连接的点的cost进行更新
status[desV].second = status[minIndex].second + adj.cost;
}
}
for (int i = 0; i < status.size(); ++i)
{
cout << "vertexIndex :" << i << " cost: " << status[i].second << endl;
}
}
以下为测试代码
inline void testDijkstra()
{
std::cout << "testDijkstra :" << std::endl;
vector<int>vec;
//sort(vec.begin(), vec.end(), less());
typedef JpGraph::Vertex vertex;
typedef JpGraph::AdjAcent adj;
vertex v0(0, 0);
vertex v1(1, 1);
vertex v2(2, 1);
vertex v3(3, 2);
vertex v4(4, 2);
vertex v5(5, 3);
vertex v6(6, 2);
v0.degree = vector { adj(1,&v3),adj{ 2,&v1 } };
v1.degree = vector { adj{ 3,&v3 },adj{ 2,&v4 } };
v2.degree = vector { adj{ 5,&v5 },adj{ 4,&v0 } };
v3.degree = vector { adj{ 8,&v5 },adj{ 2,&v2 },adj{ 2,&v4 },adj{ 4,&v6 } };
v4.degree = vector { adj{ 6,&v6 }, };
v5.degree = vector ();
v6.degree = vector { adj{ 1,&v5 } };
JpGraph graph;
graph.buildGraph(vector {v0, v1, v2, v3, v4, v5, v6});
graph.lowestCost(v0);
}
以下为top排序,top排序的思想我也不说了,网上一搜都有,以下仅实现
inline void JpGraph::topSort()
{
deque q;
for(const Vertex& vertex : vertexs)
{
if (vertex.inDegree == 0)//将所有入度为0的点加入
q.push_back(vertex);
}
while(q.size()!=0)//依次将与入度为0的点相连的点加入,并将入度0的点pop掉,此处既是一个DFS
{
auto i = q.front(); q.pop_front();
cout<" "; //通过简单的cout代表访问点
for(auto& adj : i.degree)
{
auto ptr = adj.ptr;
--(ptr->inDegree);
if (ptr->inDegree == 0)
q.push_back(*ptr);
}
}
}
以下为测试代码
inline void testTopSort()
{
vector<int>vec;
//sort(vec.begin(), vec.end(), less());
typedef JpGraph::Vertex vertex;
typedef JpGraph::AdjAcent adj;
vertex v0(0, 0);
vertex v1(1, 1);
vertex v2(2, 1);
vertex v3(3, 2);
vertex v4(4, 2);
vertex v5(5, 3);
vertex v6(6, 2);
v0.degree = vector { adj(1,&v3),adj{ 2,&v1 } };
v1.degree = vector { adj{ 3,&v3 },adj{ 2,&v4 } };
v2.degree = vector { adj{ 5,&v5 },adj{4,&v0} };
v3.degree = vector { adj{ 8,&v5 },adj{ 2,&v2 },adj{2,&v4},adj{ 4,&v6 } };
v4.degree = vector { adj{ 6,&v6 },};
v5.degree = vector ();
v6.degree = vector { adj{ 1,&v5 } };
JpGraph graph;
graph.buildGraph(vector {v0, v1, v2, v3, v4, v5, v6});
graph.topSort();
}
DFS和BFS我也不说废话,直接上代码,DFS和BFS的思想网上随便找
inline void JpGraph::BFS(int index)
{
map<int, bool>hasVisited;
deque<int>checkLine;
for (int i = 0; i < vertexs.size(); ++i)
hasVisited[i] = false;
checkLine.push_back(index);
while(!checkLine.empty())
{
int toTravel = checkLine.front();
checkLine.pop_front();
if (!hasVisited[toTravel])
{
hasVisited[toTravel] = true;
cout << vertexs[toTravel].index + 1 << " ";
for(const auto& i : vertexs[toTravel].degree)
{
auto toPAt = *(i.ptr);
if(!hasVisited[toPAt.index])
{
checkLine.push_back(toPAt.index);
}
}
}
else;
}
}
inline void JpGraph::DFS(int index)
{
map<int, bool>hasVisited;
for (int i = 0; i < vertexs.size(); ++i)
{
hasVisited[i] = false;
}
stack<int>stk;
stk.push(index);
while (!stk.empty())
{
int toTravel = stk.top();
stk.pop();
if (hasVisited[toTravel] == false)
{
hasVisited[toTravel] = true;
cout << vertexs[toTravel].index + 1 << " ";
for (const auto& i : vertexs[toTravel].degree)
{
auto toPAt = *(i.ptr);
if (!hasVisited[toPAt.index])
{
stk.push(toPAt.index);
}
}
}
else;
}
}
测试代码
inline void testDFSAndBFS()
{
vector<int>vec;
//sort(vec.begin(), vec.end(), less());
typedef JpGraph:: Vertex vertex;
typedef JpGraph:: AdjAcent adj;
vertex v0(0, 0);
vertex v1(1, 1);
vertex v2(2, 1);
vertex v3(3, 2);
vertex v4(4, 2);
vertex v5(5, 3);
vertex v6(6, 2);
v0.degree = vector { adj(1,&v3),adj{ 2,&v1 } };
v1.degree = vector { adj{ 3,&v3 },adj{ 2,&v4 } };
v2.degree = vector { adj{ 5,&v5 },adj{ 4,&v0 } };
v3.degree = vector { adj{ 8,&v5 },adj{ 2,&v2 },adj{ 2,&v4 },adj{ 4,&v6 } };
v4.degree = vector { adj{ 6,&v6 }, };
v5.degree = vector ();
v6.degree = vector { adj{ 1,&v5 } };
JpGraph graph;
graph.buildGraph(vector {v0, v1, v2, v3, v4, v5, v6});
std::cout << "testDFS :" << std::endl;
graph.DFS(0);
cout << "test BFS" << endl;
graph.BFS(0);
}