邻接矩阵:采用二维数组的形式来存储图或网。
有向、无向图,有向、无向网均可以采用邻接矩阵的方式存储,下面分别分析一些须要注意的细节点:
1,有向图:有向图的邻接矩阵不根据主对角线对称
2,无向图:根据主对角线对称(由于对称,因此咱们只需填充上半三角(或下半三角)便可,但这样也会浪费不少的存储空间,因此此时若咱们再利用矩阵压缩的办法来压缩存储为一维数组,那么这一弊端将会被降到最小)
3,有向网:与有向图相似,可是每条边都被赋有权重值
4,无向网:与无向图相似,可是每条边都被赋有权重值(也可压缩存储节约内存)node
从整体上来看,邻接矩阵适合于稠密图ios
设边数为e,节点数为n,那么
当 e >> 1 / 2 * n * (n - 1)
时,用邻接矩阵比邻接表更节省空间c++
邻接表的特色就是用表头存储全部的图节点,在存储有向图时,在每一个表头结点后都接上以它为弧尾的弧的弧首节点(有的拗口)。这样咱们可以很容易的获得一个顶点的出度(即相对应的那个表头结点链表的链表节点个数),并且更好的是咱们将邻接表转为逆邻接表是很是方便的,这意味着咱们会很容易知道每一个节点的入度!
缺点:邻接表的缺陷呢,就是若是你想知道节点i和节点j之间是否直接相连时你须要去到表头节点i和j去分别遍历该条链表。这和邻接矩阵来比显然是麻烦许多的。
因此要合理选择存储结构。web
从整体上来看,邻接表适合于稀疏图数组
设边数为e,节点数为n,那么
当 e << 1 / 2 * n * (n - 1)
时,用邻接表比邻接矩阵更节省空间ide
看代码,svg
#include <iostream> using namespace std; //-----------------------------------------图的邻接矩阵存储结构实现--------------------------------// #define MAXNUM 20 //最大节点个数 //图的种类类:有向图,有向网,无向图,无向网 typedef enum { DG, //有向图 DN, //有向网 UDG, //无向图 UDN //无向网 } Graph_type; //图类 class Graph { public: Graph(int node, int edge, Graph_type type) : node_num(node), edge_num(edge), kind(type) { for (int i = 0; i < node_num; ++i) for (int j = 0; j < node_num; ++j) matrix[i][j] = 0; //初始化 } int CreateMatrix(); void display() const; Graph_type kind; int edge_num, node_num; int matrix[MAXNUM][MAXNUM]; //邻接矩阵 }; //创建邻接矩阵 int Graph::CreateMatrix() { cout << "输入两个顶点序号以及一个1表示有边(网须要输入权重值,可为1)" << endl; int i; int tmpNode1, tmpNode2, weight; for (i = 0; i < edge_num; ++i) { cout << "输入第" << i + 1 << "条边的信息: (" << edge_num - i << "条待输入) "; cin >> tmpNode1 >> tmpNode2 >> weight; //不考虑非法输入 --tmpNode1, --tmpNode2; matrix[tmpNode1][tmpNode2] = (kind == DG || kind == UDG) ? 1 : weight; matrix[tmpNode2][tmpNode1] = (kind == UDG || kind == UDN) ? weight : 0; } cout << "输入成功" << endl; } //输出邻接矩阵 void Graph::display() const { for (int i = 0; i < node_num; ++i) {for (int j = 0; j < node_num; ++j) cout << matrix[i][j] << " "; cout << endl;} system("pause"); } int main() { cout << "请输入节点数,边数,以及图的种类(0, 1, 2, 3来表示): " << endl; int node, edge, type_; Graph_type type; cin >> node >> edge >> type_; //忽略非法输入 type_ == 0 ? type = DG : (type_ == 1 ? type = DN : (type_ == 2 ? type = UDG : type = UDN)); Graph G(node, edge, type); //建图 G.CreateMatrix(); //创建邻接矩阵 G.display(); //输出邻接矩阵 return 0; }
能够看到很是完美的实现了咱们须要的功能spa
看代码,3d
#include <iostream> using namespace std; //---------------------------------------图的邻接表存储结构的创建----------------------------------// #define MAXNUM 20 //最大节点个数 typedef struct Vertex { //elemtype data; 节点的数据域这里我就省略了,只创建邻接表 int num; //节点编号 struct Vertex *next; Vertex(int x = 0, struct Vertex *ptr = nullptr) : num(x), next(ptr) {} } Vertex, *p_Vertex; typedef struct TableNode { //表头 Vertex *next; TableNode() {next = nullptr;} } TableNode, TableHead[MAXNUM]; class Graph { //有向图 public: Graph(int node, int edge) : nodeNum(node), edgeNum(edge) {} int CreateTable(); //邻接表 int CreateTable_reverse(); //逆邻接表 void displayTable(int) const; //打印邻接表 private: TableHead num; //邻接表头 TableHead numReverse; //逆邻接表头 int nodeNum, edgeNum; }; int Graph::CreateTable() { cout << "请输入弧尾节点和弧头节点(注意顺序)" << endl; //省略非法输入检查 int node1, node2; p_Vertex ptr; bool mark = false; for (int i = 0; i < edgeNum; ++i) { cin >> node1 >> node2; num[node1 - 1].next ? ptr = num[node1 - 1].next, mark = true : (num[node1 - 1].next = new Vertex(node2 - 1), mark = false); if (mark) {while(ptr->next) ptr = ptr->next; ptr->next = new Vertex(node2 - 1);} } return 0; //ok } void Graph::displayTable(int m) const { p_Vertex ptr; if (m) cout << "建成的邻接表为: " << endl; else cout << "建成的逆邻接表为: " << endl; if (m == 1)for (int i = 0; i < nodeNum; ++i) {ptr = num[i].next; cout << i << " -> "; while(ptr) {cout << ptr->num << " -> "; ptr = ptr->next;} cout << "null" << endl;} else for (int i = 0; i < nodeNum; ++i) {ptr = numReverse[i].next; cout << i << " -> "; while(ptr) {cout << ptr->num << " -> "; ptr = ptr->next;} cout << "null" << endl;} } int Graph::CreateTable_reverse() { //邻接表改逆邻接表 p_Vertex p1, p2; bool mark = false; for (int i = 0; i < edgeNum; ++i) { p1 = num[i].next; while(p1) { (p2 = numReverse[p1->num].next) ? mark = true : (numReverse[p1->num].next = new Vertex(i), 1); if (mark) {while(p2->next) p2 = p2->next; mark = false; p2->next = new Vertex(i);} p1 = p1->next; } } return 0; //ok } int main() { int node, edge; cout << "请输入图节点数和边的数目" << endl; cin >> node >> edge; Graph t(node, edge); t.CreateTable(); t.displayTable(1); cout << endl; //邻接表 t.CreateTable_reverse(); t.displayTable(0); //逆邻接表 return 0; }
同时建成了邻接表和逆邻接表,完美运行!c++11
说下个人运行环境:IDE: devc++ ;Standard: c++11;Compiler:MinGW 重心慢慢转向devc++了,这实际上是一个很好用的ide,vscode莫名编译缓慢?? 老规矩,对你有帮助的话不要吝惜你的赞喔~~peace!