图的存储:邻接矩阵和邻接表(C++)
一、临界矩阵
1.示例效果
无向图:
有向网:
2. 代码
1 #include <iostream> 2 #include <unordered_map> 3 #include <vector> 4 #include <string> 5 //storage graph by adjacency matrix 6 using std::unordered_map; 7 using std::vector; 8 using std::string; 9 enum graphType { UG, DG,UN,DN }; //无向图,有向图,无向网,有向网 10 class Graph{ 11 public: 12 unordered_map<string,int> vertex2index; //顶点的名字 ==》下标 13 vector<vector<int>> edjes; //存储边的二维数组 14 int n, e; //顶点数和边数 15 enum graphType type; //图的类型 16 Graph(int vNum=1,int eNum=0,enum graphType t=UG): 17 n(vNum),e(eNum),type(t){} 18 Graph* createGraph(); 19 20 void showGraph() { 21 std::cout << "开始显示图:\n"; 22 auto ite = vertex2index.begin(); 23 //打印节点名字横 24 std::cout << " "; 25 for (; ite!=vertex2index.end(); ite++) { 26 std::cout<<(*ite).first << " "; 27 } 28 std::cout << "\n"; 29 //打印节点 30 ite = vertex2index.begin(); 31 for (int i = 0; i < n; i++) { 32 //打印节点名字竖 33 std::cout << (*ite++).first << " "; 34 for (int j = 0; j < n; j++) { 35 //是默认填充则打印#,否则打印其权值 36 edjes[i][j] == INT_MAX ? std::cout << "# " : std::cout << edjes[i][j] << " "; 37 } 38 std::cout << "\n"; 39 } 40 } 41 }; 42 Graph* Graph::createGraph() 43 { 44 std::cout << "图的信息:\n顶点数:" << n << " 边数:" << e<<" 类型:"; 45 switch (type) { 46 case UG:std::cout << "无向图\n"; break; 47 case DG:std::cout << "有向图\n"; break; 48 case UN:std::cout << "无向网\n"; break; 49 case DN:std::cout << "有向网\n"; break; 50 } 51 //根据顶点数来构造矩阵, 无边填充INT_MAX 52 for (int i = 0; i < n; i++) { 53 vector<int> temp(n, INT_MAX); 54 edjes.emplace_back(temp); 55 } 56 //填充顶点数组,确立顶点名字和下标的映射 57 for (int i = 0; i < n; i++) { 58 string name; 59 std::cout << "输入第" << i + 1 << "个顶点的名字(string):"; 60 std::cin >> name; 61 vertex2index[name] = i; 62 } 63 //输入边的信息 64 for (int i = 0; i < e; i++) { 65 string n1, n2; 66 int pow = 1, row = 0, column = 0; 67 std::cout << "输入第" << i + 1; 68 if (type == UG || type == DG) { //UG或DG没有权值,默认显示为1 69 std::cout << "条边的弧头,弧尾:\n"; 70 std::cin >> n1 >> n2; 71 } 72 else { 73 std::cout <<"条边的弧头,弧尾,权值:\n"; //UN或DN有权值 74 std::cin >> n1 >> n2 >> pow; 75 } 76 row = vertex2index[n1]; column = vertex2index[n2]; //根据边的名字找到对应下标 77 edjes[row][column] = pow; 78 type == UG || type == UN ?edjes[column][row] = pow : 1; //如果是UG或UN则对角线对称 79 } 80 81 return this; 82 } 83 int main() 84 { 85 //示例:6节点10边有向网 86 Graph *g = new Graph(6,10,DN); 87 g->createGraph(); 88 g->showGraph(); 89 std::cin.get(); 90 }
二、邻接表
1. 示例效果
2. 代码
1 // 头文件同上 2 //edgeNode边节点 3 struct edgeNode { 4 int index; //这条边弧尾节点的下标 5 edgeNode* next; //指向下一条边 6 int weight; //这条边的权重;图的weight默认都表示为1 7 edgeNode(int n,int w=1):index(n),next(),weight(w){} 8 }; 9 //vertex 顶点节点 10 struct vertexNode { 11 string data; //顶点的名字或数据 12 edgeNode* next; //顶点节点的指针域指向边节点 13 vertexNode(string str):data(str),next(){} 14 }; 15 class AdjList { 16 vector<vertexNode*> adjList; //邻接表 17 int n, e; //顶点的个数,边的个数 18 enum graphType type; //图的类型 19 unordered_map<string, int> vertex2index; //顶点的名字 ==》下标的映射 20 public: 21 AdjList(int verNum=1,int edgNum=0,enum graphType t=UG): 22 n(verNum),e(edgNum),type(t){} 23 void createGraph() { 24 std::cout << "图的信息:\n顶点数:" << n << " 边数:" << e << " 类型:"; 25 switch (type) { 26 case UG:std::cout << "无向图\n"; break; 27 case DG:std::cout << "有向图\n"; break; 28 case UN:std::cout << "无向网\n"; break; 29 case DN:std::cout << "有向网\n"; break; 30 } 31 for (int i = 0; i < n; i++) { 32 std::cout << "请输入第" << i+1 << "个顶点的数据(名字string):"; 33 string str; std::cin >> str; 34 adjList.push_back(new vertexNode(str)); 35 vertex2index[str] = i; 36 } 37 string s1, s2; 38 for (int i = 0; i < e; i++) { 39 std::cout << "输入第" << i + 1; 40 if (type == UG || type == DG) { //UG或DG没有权值,默认显示为1 41 std::cout << "条边的弧头,弧尾:\n"; 42 std::cin >> s1 >> s2; 43 int n1 = vertex2index[s1], n2 = vertex2index[s2]; 44 edgeNode *node = new edgeNode(n2); 45 //把边节点挂上去 46 node->next = adjList[n1]->next; 47 adjList[n1]->next = node; 48 } 49 else { 50 int weight = 1; 51 std::cout << "条边的弧头,弧尾,权值:\n"; //UN或DN有权值 52 std::cin >> s1 >> s2 >> weight; 53 int n1 = vertex2index[s1], n2 = vertex2index[s2]; 54 edgeNode *node = new edgeNode(n2, weight); 55 //把边节点挂上去 56 node->next = adjList[n1]->next; 57 adjList[n1]->next = node; 58 } 59 } 60 } 61 void showGraph() { 62 std::cout << "开始显示图:\n"; 63 for (auto& i: adjList) { 64 std::cout << i->data << "->"; 65 edgeNode *cur = i->next; 66 while (cur) { 67 std::cout <<"("<< cur->index <<","<<cur->weight<<")"<< "->"; 68 cur = cur->next; 69 } 70 std::cout << "null"; 71 std::cout << "\n"; 72 } 73 } 74 }; 75 76 int main() 77 { 78 //示例:4节点5边有向网 79 AdjList *g = new AdjList(5,6,DN); 80 g->createGraph(); 81 g->showGraph(); 82 std::cin.get(); 83 std::cin.get(); 84 }