顶点计划V第一周

本周总结

和大家开会,基本了解自己在小组中负责人脸识别的任务,即在某一个环境中,将视频中有多少个人实时的显示出来。

下周规划

  1. 找段老师咨询一下相关方面的问题,已经明确了干什么,但是还没有怎么做的方向。
  2. 找到方向后开始着手了解,计划是不自己造轮子,面向github先实现一些简单的小目标(例如人脸清晰,不重叠)。
namespace link_table { /* 邻接表的实现类似于哈希桶 下标与顶点的下标一致 挂起的是 "边" */ template<class W> struct Edge { int _srci;//起点 int _dsti;//终点 W _w; //权值 Edge<W>* _next;//连接到邻接表中去 Edge(int srci, int dsti, const W& w) :_srci(srci),_dsti(dsti),_w(w) ,_next(nullptr) { } bool operator>(const Edge& e)const { return _w > e._w; } }; //邻接表 template<class V, class W, bool Direction = false> class graph { typedef Edge<W> Edge; typedef graph<V, W, Direction> self; public: graph(){} //手动初始化 graph(const V* a, size_t n) { _vertexes.reserve(n); for (int i = 0; i < n; ++i) { _vertexes.push_back(a[i]); _index[a[i]] = i; } //n行n列全部初始化为最大值 _tables.resize(n); } int GetIndexOfVertexes(const V& v) { //find比count高效, //find找到立即返回,count需要找完所有数据 auto it = _index.find(v); if (it == _index.end()) throw invalid_argument("无效参数"); return it->second; } void _AddEdge(int srci, int dsti, const W& w) { //构造边 Edge* eg = new Edge(srci, dsti, w); //头插 eg->_next = _tables[srci]; _tables[srci] = eg; if (Direction == false) { //构造边 Edge* eg = new Edge(dsti, srci, w); //头插 eg->_next = _tables[dsti]; _tables[dsti] = eg; } } void AddEdge(const V& src, const V& dst, const W& w) { //得到起点和终点的下标 int srci = GetIndexOfVertexes(src); int dsti = GetIndexOfVertexes(dst); _AddEdge(srci, dsti, w); } void Print() { //打印 下标及其对应的顶点值 for (int i = 0; i < _vertexes.size(); ++i) { cout << '[' << i << "] -> " << _vertexes[i] << endl; } cout << endl; //打印邻接表 for (int i = 0; i < _tables.size(); ++i) { //打印起点 cout << "[ " << _vertexes[i] << " : " << i << " ] -> "; //起点对应的边 Edge* cur = _tables[i]; while (cur) { cout << "[ " << _vertexes[cur->_dsti] << " : " << cur->_dsti << " : " << cur->_w << " ]" << " -> "; cur = cur->_next; } cout << "nullptr" << endl; } } //广度优先遍历 //从一个顶点出发,访问它所连接的未被访问过的顶点 void BFS(const V& src) { int n = _vertexes.size(); int srci = GetIndexOfVertexes(src); //队列和标记数组 queue<int> q; vector<bool> visited(n, false); //进队列就标记,防止同一元素多次入队列 q.push(srci); visited[srci] = true; //每层的个数 int levelsize = 1; //开始遍历 while (!q.empty()) { //一层一层的出 for (int i = 0; i < levelsize; ++i) { //访问队头元素 int front = q.front(); q.pop(); cout << front << " : " << _vertexes[front] << ' '; //所连接的未被访问过的顶点入队列 Edge* cur = _tables[front]; while (cur) { if (visited[cur->_dsti] == false) { q.push(cur->_dsti); visited[cur->_dsti] = true; } cur = cur->_next; } } cout << endl; levelsize = q.size(); } } //栈溢出风险 //void DFS(const V& src) //{ // int n = _vertexes.size(); // int srci = GetIndexOfVertexes(src); // vector<bool> visited(n, false); // _DFS(srci, visited); //} //void _DFS(int srci, vector<bool>& visited) //{ // //立即访问并标记 // cout << srci << " : " << _vertexes[srci] << endl; // visited[srci] = true; // //访问下一个相连但未访问过 // Edge* cur = _tables[srci]; // while (cur) // { // if (visited[cur->_dsti] == false) // _DFS(cur->_dsti, visited); // cur = cur->_next; // } //} void DFS(const V& src) { int n = _vertexes.size(); int srci = GetIndexOfVertexes(src); //将与当前顶点相连的第一条边入栈 stack<Edge*> st; Edge* cur = _tables[srci]; while (cur) { if (visited[top->_dsti] == false) break; cur = cur->_next; } if(cur) st.push(cur); //标记数组 vector<bool> visited(n, false); //访问当前顶点 visited[srci] = true; cout << srci << ":" << _vertexes[srci] << endl; while (!st.empty()) { //访问栈顶元素 Edge* top = st.top(); if(visited[top->_dsti] == false)//这条边未被访问过 { visited[top->_dsti] = true; cout << top->_dsti << ":" << _vertexes[top->_dsti] << endl; cur = _tables[top->_dsti];//相连的边中去 } else//这条边被访问过 { cur = top->_next;//其他边 st.pop(); } //遍历邻接表,与其连接的未被访问过的顶点 while (cur) { if (visited[cur->_dsti] == false) break; cur = cur->_next; } //未被访问过 if (cur) { st.push(cur); } } } //全局寻找边 W Kruskal(self& minTree) { int n = _vertexes.size(); minTree._index = _index; minTree._vertexes = _vertexes; minTree._tables.resize(n, nullptr); //优先级队列存储边 priority_queue<Edge, vector<Edge>, greater<Edge>> minpq; for (int i = 0; i < _tables.size(); ++i) { //无向图的邻接表中,边存了双份 Edge* cur = _tables[i]; while (cur) { minpq.push(*cur); cur = cur->_next; } } UnionFindSet ufs(n); //权值、边数 W totalw = W(); int size = 0; //开始选边 while (!minpq.empty()) { //选出最小边 Edge min = minpq.top(); minpq.pop(); //判环 if (ufs.InSet(min._srci, min._dsti)) { cout << "构成环:" << _vertexes[min._srci] << "->" << _vertexes[min._dsti] << ":" << min._w << endl; continue; } //进入最小生成树 minTree._AddEdge(min._srci, min._dsti, min._w); cout << _vertexes[min._srci] << "->" << _vertexes[min._dsti] << ":" << min._w << endl; //进入最小生成树的顶点在同一个集合 ufs.Union(min._srci, min._dsti); ++size; totalw += min._w; if (size == n - 1) break; } if (size == n - 1) return totalw; else return W(); } //普利姆算法的实现刚好弥补了边进两次的缺陷 W Prim(self& minTree, const V& src) { int srci = GetIndexOfVertexes(src); int n = _vertexes.size(); minTree._index = _index; minTree._vertexes = _vertexes; minTree._tables.resize(n, nullptr); //在最小生成树中的顶点 vector<bool> in(n, false); in[srci] = true; //优先级队列存储边 priority_queue<Edge, vector<Edge>, greater<Edge>> minpq; //从当前节点连接出去的边 //无向图的邻接表中,边存了双份 Edge* cur = _tables[srci]; while (cur) { minpq.push(*cur); cur = cur->_next; } //权值、边数 W totalw = W(); int size = 0; //开始选边 while (!minpq.empty()) { //选出最小边 Edge min = minpq.top(); minpq.pop(); //判环 if (in[min._dsti] == true) { cout << "构成环:" << _vertexes[min._srci] << "->" << _vertexes[min._dsti] << ":" << min._w << endl; continue; } //进入最小生成树 minTree._AddEdge(min._srci, min._dsti, min._w); cout << _vertexes[min._srci] << "->" << _vertexes[min._dsti] << ":" << min._w << endl; //进入最小生成树的顶点 in[min._dsti] = true; ++size; totalw += min._w; if (size == n - 1) break; //先做上述判断,再持续进边 Edge* cur = _tables[min._dsti]; while (cur) { //边的顶点不再最小生成树内 if(in[cur->_dsti] == false) minpq.push(*cur); cur = cur->_next; } } if (size == n - 1) return totalw; else return W(); } private: vector<V> _vertexes;//顶点集合 unordered_map<V, int> _index;//顶点映射下标 vector<Edge*> _tables;//邻接表 存放边的集合 }; void TestGraph() { string a[] = { "张三", "李四", "王五", "赵六" }; graph<string, int> g1(a, 4); g1.AddEdge("张三", "李四", 100); g1.AddEdge("张三", "王五", 200); g1.AddEdge("王五", "赵六", 30); g1.Print(); } void TestGraphDBFS() { string a[] = { "张三", "李四", "王五", "赵六", "周七" }; graph<string, int> g1(a, sizeof(a) / sizeof(string)); g1.AddEdge("张三", "李四", 100); g1.AddEdge("张三", "王五", 200); g1.AddEdge("王五", "赵六", 30); g1.AddEdge("王五", "周七", 30); g1.BFS("张三"); cout << endl; g1.DFS("张三"); } void TestGraphMinTree() { const char* str = "abcdefghi"; graph<char, int> g(str, strlen(str)); g.AddEdge('a', 'b', 4); g.AddEdge('a', 'h', 8); //g.AddEdge('a', 'h', 9); g.AddEdge('b', 'c', 8); g.AddEdge('b', 'h', 11); g.AddEdge('c', 'i', 2); g.AddEdge('c', 'f', 4); g.AddEdge('c', 'd', 7); g.AddEdge('d', 'f', 14); g.AddEdge('d', 'e', 9); g.AddEdge('e', 'f', 10); g.AddEdge('f', 'g', 2); g.AddEdge('g', 'h', 1); g.AddEdge('g', 'i', 6); g.AddEdge('h', 'i', 7); graph<char, int> kminTree; cout << "Kruskal:" << g.Kruskal(kminTree) << endl; //kminTree.Print(); cout << endl; graph<char, int> pminTree; cout << "Prim:" << g.Prim(pminTree, 'a') << endl; //pminTree.Print(); } } void DFS(const V& src)函数实现的广度优先遍历合理吗
09-29
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值