图的邻接多重表和搜索(C++版本)
最近在学数据结构,学到图这一章,网上的C++版本的代码乱得不行,所以自己写了一个完整C++版本的放这里。
用邻接多重表表示一个无向图,并给出DFS和BFS搜索代码。邻接多重表好处就是贼直观,几条边就几个边表的元素。
代码如下:
边表节点定义(其实就是边的定义)
- typedef struct EdgeNode //邻接多重表
- {
- int iVertex;
- EdgeNode* iLink;
- int jVertex;
- EdgeNode* jLink;
- };
顶点表节点的定义
- template <typename Type>
- struct VextexNode //邻接多重表的顶点表
- {
- Type Data;
- EdgeNode* TailLink;
- Mark Flag;
- };
最后是图的模板类
- #ifndef MULADJACENCYLIST_H
- #define MULADJACENCYLIST_H
- #include "SideNode.h"
- #include "VexNode.h"
- #include <iostream>
- #include <vector>
- #include <list>
- #include <set>
- using namespace std;
- template <typename Type, int N>
- class MulAdjacencyList
- {
- public:
- MulAdjacencyList();
- ~MulAdjacencyList();
- void AddEdge();
- int DeleteEdge(int x, int y);
- void DFS(int x, const Type& Value);
- void BFS(int x, const Type& Value);
- private:
- int InitEdgeNum(); //构造函数中先输入图的边数
- int NextIndex(int CurIndex); //查找最近的一个邻接点,CurIndex为点的下标而不是值
- void BFSHelper(set <int> SourceList, const Type& Value); //BFS真正的递归函数
- void AllNextIndex(int i); //和i相连的所有邻接点,i为点的下标而不是值
- VextexNode <Type> VertexArray[N]; //顶点表
- EdgeNode* LastPtr(int x);
- int EdgeNums; //当前的边数
- vector <int> Temp; //用来存放搜索结果的容器
- set <int> TempList; //用来存放AllNextIndex结果的容器
- };
- template <typename Type, int N>
- void MulAdjacencyList<Type, N>::AddEdge() //添加一条x到y的无向边
- {
- cout << "Enter the edge wanna insert!" << endl;
- int i, j;
- if (cin >> i >> j)
- {
- EdgeNode* TarPtr = new EdgeNode;
- TarPtr->iVertex = i;
- TarPtr->jVertex = j;
- TarPtr->iLink = VertexArray[i].TailLink;
- TarPtr->jLink = VertexArray[j].TailLink;
- VertexArray[i].TailLink = TarPtr;
- VertexArray[j].TailLink = TarPtr;
- EdgeNums++;
- }
- else
- cin.clear();
- }
- template <typename Type, int N>
- int MulAdjacencyList<Type, N>::InitEdgeNum()
- {
- cout << "Enter the quantity of edges!"<< endl;
- cin >> EdgeNums;
- return EdgeNums;
- }
- template <typename Type, int N>
- EdgeNode* MulAdjacencyList<Type, N>::LastPtr(int x) //找到和x相关的最后一条边
- {
- EdgeNode* Temp = VertexArray[x].TailLink;
- EdgeNode* LastTemp = Temp;
- while (Temp != NULL)
- {
- if (Temp->iVertex == x)
- {
- LastTemp = Temp;
- Temp = Temp->iLink;
- }
- else if (Temp->jVertex == x)
- {
- LastTemp = Temp;
- Temp = Temp->jLink;
- }
- }
- return LastTemp;
- }
- template <typename Type, int N>
- MulAdjacencyList <Type, N>::MulAdjacencyList()
- {
- cout << "enter the vertex for the graph!" << endl;
- for (int i = ; i != N; ++i)
- {
- cin >> VertexArray[i].Data;
- VertexArray[i].TailLink = NULL;
- VertexArray[i].Flag = No;
- }
- int Temp = InitEdgeNum();
- for (int i = ; i != Temp; ++ i)
- AddEdge();
- }
- template <typename Type, int N>
- int MulAdjacencyList<Type, N>::DeleteEdge(int x, int y) //删除x到y的一条无向边
- {
- if (x == y)return ;
- EdgeNode* Q = VertexArray[x].TailLink; //Q的下一条边就是要删除的边
- EdgeNode* P = VertexArray[x].TailLink; //先从x出发找到要删除的边,调整完x的边的次序,得到指针,最后再删除
- if (P && P->jVertex == y) //假如第一条边就是待删除的边, P是前向判断,避免P为NULL的情况下还执行P->jVertex
- VertexArray[x].TailLink = P->iLink;
- else if (P && P->iVertex == y)
- VertexArray[x].TailLink = P->jLink;
- else //假如第一条边不是要删除的边,则向下查找
- {
- while (P)
- {
- if (P->iVertex == x && P->jVertex != y)//不是要删除的边
- {
- Q = P;
- P = P->iLink;
- }
- else if (P->jVertex == x && P->iVertex != y)
- {
- Q = P;
- P = P->jLink;
- }
- else //找到了邻接点y
- break;
- }
- if (P == NULL)
- {
- return ; //这里可以加入一句警告“Not Found”
- }
- else if (P->iVertex == x && P->jVertex == y) //找到了边(x,y),调整x的边的次序
- {
- if (Q->iVertex == x)
- Q->iLink = P->iLink;
- else
- Q->jLink = P->iLink;
- }
- else if (P->iVertex == y && P->jVertex == x)
- {
- if (Q->iVertex == x)
- Q->iLink = P->jLink;
- else
- Q->jLink = P->jLink;
- }
- }
- P = VertexArray[y].TailLink; //从y出发开始查找,调整y的边的次序
- if (P && P->iVertex == x)
- VertexArray[y].TailLink = P->jLink;
- else if (P && P->jVertex == x)
- VertexArray[y].TailLink = P->iLink;
- else
- {
- while (P != NULL)
- {
- if (P->iVertex == y && P->jVertex != x)
- {
- Q = P;
- P = P->iLink;
- }
- else if (P->jVertex == y && P->iVertex != x)
- {
- Q = P;
- P = P->jLink;
- }
- else
- break;
- }
- if (P == NULL) //由于上面打了一次警告,这里就不打警告了
- return ;
- else if (P->iVertex == y && P->jVertex == x)
- {
- if (Q->iVertex == y)
- Q->iLink = P->iLink;
- else
- Q->jLink = P->iLink;
- }
- else if ((P->jVertex == y && P->iVertex == x))
- {
- if (Q->iVertex == y)
- Q->iLink = P->jLink;
- else
- Q->jLink = P->jLink;
- }
- }
- cout << x << endl << y << endl<<"yici"<<endl;
- if (P != NULL) delete P; //调整完线序了,删掉边
- --EdgeNums;
- return ;
- }
- template <typename Type, int N>
- MulAdjacencyList <Type, N>::~MulAdjacencyList()
- {
- for (int i = ; i != N; ++i)
- {
- for (int j = ; j != N; ++j)
- DeleteEdge(i,j);
- }
- }
- template <typename Type, int N>
- void MulAdjacencyList <Type, N>::AllNextIndex(int i) //找到和i相关联的所有的点
- {
- EdgeNode* Ptr = VertexArray[i].TailLink;
- while (Ptr != NULL)
- {
- if (Ptr->iVertex == i)
- {
- if (VertexArray[Ptr->jVertex].Flag != Yes)TempList.insert(Ptr->jVertex);
- Ptr = Ptr->iLink;
- }
- else
- {
- if (VertexArray[Ptr->iVertex].Flag != Yes)TempList.insert(Ptr->iVertex);
- Ptr = Ptr->jLink;
- }
- }
- }
- template <typename Type, int N>
- int MulAdjacencyList <Type, N>::NextIndex(int CurIndex)
- {
- EdgeNode* Ptr = VertexArray[CurIndex].TailLink;
- while (Ptr != NULL)
- {
- if (Ptr->iVertex == CurIndex)
- {
- if (VertexArray[Ptr->jVertex].Flag == No){
- return Ptr->jVertex;
- }
- else
- Ptr = Ptr->iLink;
- }
- else if (Ptr ->jVertex == CurIndex)
- {
- if (VertexArray[Ptr->iVertex].Flag == No){
- return Ptr->iVertex;
- }
- else
- Ptr = Ptr->jLink;
- }
- }
- if (Ptr == NULL) { return N; }
- }
- template <typename Type, int N>
- void MulAdjacencyList <Type, N>::DFS(int x, const Type& Value) //x为起始的下标,Value为查找的值
- {
- if (VertexArray[x].Data == Value)
- {
- Temp.push_back(x);
- }
- VertexArray[x].Flag = Yes;
- int TempIndex = NextIndex(x);
- while (TempIndex != N)
- {
- DFS(TempIndex, Value);
- TempIndex = NextIndex(x);
- }
- for (vector <int>::const_iterator i = A.Temp.begin(); i != A.Temp.end(); ++i) //打印找到的元素
- cout << *i << endl;
- }
- template <typename Type, int N>
- void MulAdjacencyList <Type, N>::BFSHelper(set <int> SourceList,const Type& Value)
- {
- if (!SourceList.empty())
- {
- for (set <int>::const_iterator i = SourceList.begin(); i != SourceList.end(); ++i)
- {
- VertexArray[*i].Flag = Yes;
- if (VertexArray[*i].Data == Value)
- Temp.push_back(*i);
- }
- for (set <int>::const_iterator i = SourceList.begin(); i != SourceList.end(); ++i)
- {
- AllNextIndex(*i);
- }
- SourceList = TempList;
- TempList.clear();
- BFSHelper(SourceList, Value);
- }
- }
- template <typename Type, int N>
- void MulAdjacencyList <Type, N>::BFS(int x, const Type& Value)
- {
- set <int> Set;
- Set.insert(x);
- BFSHelper(Set, Value);
- }
- #endif
大类的代码有点乱,先挖个坑以后有空再来填上,希望对各位和自己有帮助。
图的邻接多重表和搜索(C++版本)的更多相关文章
- 图->存储结构->邻接多重表
文字描述 邻接多重表是无向图的另一种链式存储结构. 虽然邻接表是无向图的一种很有效的存储结构,在邻接表中容易求得顶点和边的各种信息. 但是,在邻接表中每一条边(vi,vj)有两个结点,分别在第i个和第 ...
- 数据结构学习笔记05图 (邻接矩阵 邻接表-->BFS DFS、最短路径)
数据结构之图 图(Graph) 包含 一组顶点:通常用V (Vertex) 表示顶点集合 一组边:通常用E (Edge) 表示边的集合 边是顶点对:(v, w) ∈E ,其中v, w ∈ V 有向边& ...
- 数据结构之---C语言实现图的邻接表存储表示
// 图的数组(邻接矩阵)存储表示 #include <stdio.h> #include <stdlib.h> #include <string.h> #defi ...
- 图的邻接表存储表示(C)
//---------图的邻接表存储表示------- #include<stdio.h> #include<stdlib.h> #define MAX_VERTEXT_NUM ...
- 图的邻接表存储 c实现
图的邻接表存储 c实现 (转载) 用到的数据结构是 一个是顶点表,包括顶点和指向下一个邻接点的指针 一个是边表, 数据结构跟顶点不同,存储的是顶点的序号,和指向下一个的指针 刚开始的时候把顶点表初始化 ...
- 基于visual Studio2013解决算法导论之053图的邻接表表示
题目 图的邻接表表示 解决代码及点评 // 图的邻接表表示.cpp : 定义控制台应用程序的入口点. // #include <iostream> #include <sta ...
- c_数据结构_图_邻接表
课程设计------邻接表 图的遍历实现课程设计:https://files.cnblogs.com/files/Vera-y/图的遍历_课程设计.zip #include<stdio.h> ...
- 图论——图的邻接表实现——Java语言(完整demo)
1.图的简单实现方法——邻接矩阵 表示图的一种简单的方法是使用一个一维数组和一个二维数组,称为领接矩阵(adjacent matrix)表示法. 对于每条边(u,v),置A[u,v]等于true:否则 ...
- 稀疏图(邻接链表),并查集,最短路径(Dijkstra,spfa),最小生成树(kruskal,prim)
全部函数通过杭电 1142,1162,1198,1213等题目测试. #include<iostream> #include<vector> #include<queue ...
随机推荐
- Activity之间传递参数(三)
------siwuxie095 传递值对象,即自定义的有数据类型的对象 1.首先 new 一个 class:User,用于创建自定义对象,同时右键 Generate 出 Constructor.se ...
- MM常用表
Table 表描述 MKPF 物料凭证抬头 MSEG 物料凭证段
- atoi()函数
原型:int atoi (const char *nptr) 用法:#include <stdlib.h> 功能:将字符串转换成整型数:atoi()会扫描参数nptr字符串,跳过前 ...
- (转)jQuery EasyUI Tree - TreeGrid动态加载子节点
有时我们已经得到充分的分层树形网格(TreeGrid)的数据. 我们还想让树形网格(TreeGrid)按层次惰性加载节点. 首先,只加载顶层节点. 然后点击节点的展开图标来加载它的子节点. 本教程展示 ...
- 加载音频Audio
var cameraAudio = new Audio(); cameraAudio.src = 'camera.wav'; // 设置音频对象的属性,预加载视频 var options_audio ...
- HTML超标记语言
Html超文本标记语言,负责描绘Web世界的骨架. 〇.工具 http;//www.w3cchool.com.cn 一.Tim Bemers Lee 万维网之父: Html设计者: W3C创始人: ...
- 【如何快速的开发一个完整的iOS直播app】(播放篇)
原文转自:袁峥Seemygo 感谢分享.自我学习 前言 在看这篇之前,如果您还不了解直播原理,请查看上篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,集成ijkpl ...
- Python 字符串分割的方法
在平时工作的时候,发现对于字符串分割的方法用的比较多,下面对分割字符串方法进行总结一下:第一种:split()函数split()函数应该说是分割字符串使用最多的函数用法:str.split('分割符' ...
- cassandra-执行请求入口函数
参考 http://ju.outofmemory.cn/entry/115864 org.apache.cassandra.transport.Message中静态Dispatcher的 channe ...
- 了解Hadoop和大数据
1. 场景: 现在人产生数据越来越快,机器则更快,所以需要另外的一种处理数据的方法. 硬盘容量增加,但是性能没跟上,解决办法是将数据分到多块硬盘,然后同时读取. 问题: 硬件问题 -- 复 ...