Kahn算法-拓扑排序
来源:互联网 发布:js清空数组中所有元素 编辑:程序博客网 时间:2024/03/29 23:26
/*时间:2015/11/22内容:拓扑排序的实现(可用于判断图中是否有环路)概述:基于Kahn算法(DFS算法的实现),采用邻接表的方式来存储有向无权图,并实现对图的拓扑排序,在给出拓扑序列的同时,也能判断图中是否存在环路(即没有拓扑序列)操作:邻接表的创建 邻接表的打印 拓扑排序及其辅助函数*/#include<iostream>#include<vector>#include<deque>#include<memory>#include<algorithm>#include<utility>class edgesList//边表{public: int index;//表示与之相连的顶点在顶点表中的编号 edgesList *next;//表示与之相连的其它顶点 edgesList(int index, edgesList* next) :index(index), next(next){}};class vertexList//顶点表{public: char vertex;//当前顶点用字符表示 edgesList *edges;//表示与之相连的顶点,用智能指针管理 vertexList(char vertex, edgesList* next) :vertex(vertex), edges(next){}};class Graphe{public: std::vector<vertexList> g;//图(邻接表存储方式) std::vector<char> topologicallysort;//拓扑排序结果 std::vector<std::pair<int,bool>> incoming; //记录顶点的入度和是否已经从图中删除public: //创建并初始化邻接表 Graphe() { int vertexNum=0, edgesNum=0; std::cout << "输入图中的顶点数和边数 "; std::cin >> vertexNum >> edgesNum; std::cout << "输入图中的所有顶点编号 "; for (int i = 0; i < vertexNum; ++i) { char vertexName; std::cin >> vertexName; g.push_back({ vertexName, NULL }); } for (auto &v : g) { int n = 0; std::cout << "输入从" << v.vertex<<"出发的顶点的数量和它们在数组中的下标"; std::cin >> n; incoming.push_back({ 0, false });//记录每个定点的入度 for (int i = 0; i < n; ++i)//创建时采用头插法 { int index=0; std::cin >> index; edgesList* temp =new edgesList( index, NULL ); if (v.edges == NULL) v.edges = temp;//此时直接插在头部 else { temp->next = v.edges; v.edges = temp; } } } } //依次释放表中内存 ~Graphe() { for (auto &v : g) { edgesList* ptr = v.edges; while (ptr) { edgesList* temp = ptr; ptr = ptr->next; free(temp); } } } //打印邻接表 void type() { for (auto &v : g) { auto temp = v.edges; std::cout << v.vertex; while (temp) { std::cout << "->" << temp->index; temp = temp->next; } std::cout << "-> End\n"; } } //初始化incoming和S void initialize(std::deque<char>& S) { for (int i = 0; i < g.size();++i) { edgesList* temp = g[i].edges; while (temp) { ++incoming[temp->index].first;//没发现一次入的边,则对应的入度加一 temp = temp->next; } } for (int i = 0; i < g.size(); ++i) { if (!incoming[i].first)//如果入度为0,则加入S中 { S.push_back(g[i].vertex); incoming[i].second = true; } } } //每次删除一个顶点后更新所有顶点的入度 void updateIncoming(std::vector<vertexList>::iterator v) { edgesList* temp=v->edges; while (temp)//依次更新顶点的入度 { if(incoming[temp->index].first) --incoming[temp->index].first; temp = temp->next; } } //将表中入度为0且没有加入过S中的顶点纳入S void updateS(std::deque<char>& S) { for (int i = 0; i < g.size(); ++i)//遍历整个入度表 if (!incoming[i].first && !incoming[i].second)//如果入度为0且没有加入S,则将之加入S后将标志域设置为true; { S.push_back(g[i].vertex); incoming[i].second = true; } } //拓扑排序 bool Kahn() { /* std::vector<vertexList> g; //图(邻接表存储方式) std::vector<char> topologicallysort; //拓扑排序结果 std::vector<int> incoming; //记录顶点的入度 std::deque<char> S; //没有入度的顶点的集合 */ std::deque<char> S; initialize(S); while (!S.empty()) { char curNode = S[0]; topologicallysort.push_back(curNode);//插入一个点进入拓扑序列 S.erase(S.begin());//从没有入度的顶点集合中删除该顶点 updateIncoming(std::find_if(g.begin(), g.end(), //更新入度 [curNode](vertexList c)->bool{ return c.vertex == curNode; })); updateS(S);//更新集合S } if (topologicallysort.size()!=g.size())//如果拓扑排序的节点数和图中节点数不一致,则说明有环存在 return false; else return true; }};int main(){ Graphe g; g.type(); if (g.Kahn()) for (auto c : g.topologicallysort) std::cout << c << ' '; else std::cout << "circle"; return 0;}
0 0
- Kahn算法-拓扑排序
- 拓扑排序:Kahn算法
- 拓扑排序-Kahn算法
- HDU-1258(拓扑排序Kahn算法)
- 拓扑排序(Kahn算法和基于DFS求解法)
- hdu1285确定比赛名次(拓扑排序kahn算法)
- 拓扑排序的两种实现:Kahn算法和dfs算法
- 算法期中1004. Kahn算法求解有向无环图拓扑排序
- 【算法设计与数据结构】拓扑排序算法的实现——Kahn算法及基于dfs的算法
- 分别使用Kahn和DFS实现拓扑排序
- 基于入度的拓扑排序(Kahn's Algorithm)
- Kahn算法
- hdoj1285 确定比赛名次 topo排序 Kahn算法 (新手向)
- 贪婪算法--- 拓扑排序
- 贪婪算法--- 拓扑排序
- 拓扑排序算法
- 拓扑排序算法
- 拓扑排序算法
- Linux find命令用法小结
- 栈的实现(链式)
- openstack用bosh安装cloudfoundry(四)---用micro bosh部署bosh
- web学习-jsp客户端与Servlet的关联
- hdu 1016 Prime Ring Problem dfs
- Kahn算法-拓扑排序
- zzulioj 1783: 简单的求和 (筛选求和) 求和预处理 好题
- HDU 1008-Elevator
- HDU 5569 长度为n的上升子序列个数d (大数模板+DP)
- QTime中currentTime()的使用方法
- 前序遍历的层号表示转孩子数组表示法
- 大白-Dijksta模板
- 线索二叉树
- 《Go语言入门》如何在Windows下安装Go语言编程环境