如题。
方便起见,用邻接表,表示无向图;用邻接矩阵,表示有向图。
以下代码为C#,Java类似,可以自己完成。
ps:java和c#语言,即使实现细节不一样,基本可以完成相同的功能。比如LinkedList,java中大量用到index,c#则使用LinkedListNode辅助,都可以完成各种“风骚”操作。
虽然这里的例子没有用到,需要的同学也可以自行研究。
邻接表类(无向图):
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { //无向图(不考虑孤立点)邻接表表示法 class MyTable { Node[] nodes; //构造方法1,获得图5-2所示图形 public MyTable() { int n = 5; nodes = new Node[n]; LinkedList<int> t; for (int i = 0; i < n; i++) { nodes[i] = new Node("v" + i); } t = new(); t.AddLast(1); t.AddLast(2); t.AddLast(4); nodes[0].next = t; t = new(); t.AddLast(0); t.AddLast(2); nodes[1].next = t; t = new(); t.AddLast(0); t.AddLast(1); t.AddLast(4); nodes[2].next = t; t = new(); t.AddLast(4); nodes[3].next = t; t = new(); t.AddLast(0); t.AddLast(2); t.AddLast(3); nodes[4].next = t; } //构造方法2,获得边长为n的任意无向图 public MyTable(int n) { LinkedList<int> t; int j; if (n == -1) { Console.WriteLine("输入图中节点的个数:"); n = int.Parse(Console.ReadLine()); } nodes = new Node[n]; Console.WriteLine("输入每个节点的名称(每个名称回车结束)"); for (int i = 0; i < n; i++) { nodes[i] = new Node(Console.ReadLine()); } for (int i = 0; i < n; i++) { Console.WriteLine($"输入节点{nodes[i].v}的边(序号表示,每个序号回车,-1结束)"); j = int.Parse(Console.ReadLine()); t = new(); do { t.AddLast(j); j = int.Parse(Console.ReadLine()); } while (j != -1); nodes[i].next = t; } } //按构造输入的方式输出图,测试用。 public void testShow() { foreach (var item in nodes) { Console.Write($"节点{item.v},边:"); foreach (var item1 in item.next) { Console.Write(item1 + " "); } Console.WriteLine(); } } } //顶点(值和指向边的指针) class Node { public string v; public LinkedList<int> next; public Node(string x) { v = x; } } }
测试主类:
static void Main(string[] args) { MyTable mt; //mt= new MyTable(); mt = new MyTable(5); mt.testShow(); }
运行结果
默认构造:
节点v0,边:1 2 4 节点v1,边:0 2 节点v2,边:0 1 4 节点v3,边:4 节点v4,边:0 2 3
指定节点和边的构造:
输入每个节点的名称(每个名称回车结束) v0 v1 v2 v3 v4 输入节点v0的边(序号表示,每个序号回车,-1结束) 1 2 4 -1 输入节点v1的边(序号表示,每个序号回车,-1结束) 0 2 -1 输入节点v2的边(序号表示,每个序号回车,-1结束) 0 1 4 -1 输入节点v3的边(序号表示,每个序号回车,-1结束) 4 -1 输入节点v4的边(序号表示,每个序号回车,-1结束) 0 2 3 -1 节点v0,边:1 2 4 节点v1,边:0 2 节点v2,边:0 1 4 节点v3,边:4 节点v4,边:0 2 3
邻接矩阵(有向图)代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { //有向图邻接矩阵表示法(图中至少有一条边) class MyMatrix { public string[] nodes; public int[,] edges; //构造方法1,获得图5-1所示图形 public MyMatrix() { nodes = new string[5]; edges = new int[5, 5]; for (int i = 0; i < nodes.Length; i++) { nodes[i] = "v" + i; } edges[0, 2] = 1; edges[0, 4] = 1; edges[1, 0] = 1; edges[2, 1] = 1; edges[2, 3] = 1; edges[4, 3] = 1; } //构造方法2,获得边长为n的任意有向图 public MyMatrix(int n) { int start, end; if (n == -1) { Console.WriteLine("输入图中节点的个数:"); n = int.Parse(Console.ReadLine()); } nodes = new string[n]; Console.WriteLine("输入每个节点的名称(每个名称回车结束)"); for (int i = 0; i < n; i++) { nodes[i] = Console.ReadLine(); } edges = new int[n,n]; Console.WriteLine($"输入边起点(序号表示,每个序号回车,起点-1结束)"); start = int.Parse(Console.ReadLine()); end = int.Parse(Console.ReadLine()); do { edges[start, end] = 1; Console.WriteLine($"输入边起点(序号表示,每个序号回车,起点-1结束)"); start = int.Parse(Console.ReadLine()); end = int.Parse(Console.ReadLine()); } while (start != -1); } //按顶点、矩阵方式输出图,测试用。 public void testShow() { Console.Write("顶点信息:"); foreach (var item in nodes) { Console.Write(item + " "); } Console.WriteLine(); Console.WriteLine("邻接矩阵:"); for (int i = 0; i < edges.GetLength(0); i++) { for (int j = 0; j < edges.GetLength(1); j++) { Console.Write(edges[i, j] + " "); } Console.WriteLine(); } } } }
主程序:
static void Main(string[] args) { MyMatrix mm; mm = new(); //mm = new(5); mm.testShow(); }
默认构造的运行结果:
顶点信息:v0 v1 v2 v3 v4 邻接矩阵: 0 0 1 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0
用户指定图(P128图5-22)的运行结果:
输入每个节点的名称(每个名称回车结束) v0 v1 v2 v3 v4 输入边起点(序号表示,每个序号回车,起点-1结束) 0 1 输入边起点(序号表示,每个序号回车,起点-1结束) 0 4 输入边起点(序号表示,每个序号回车,起点-1结束) 0 3 输入边起点(序号表示,每个序号回车,起点-1结束) 1 2 输入边起点(序号表示,每个序号回车,起点-1结束) 3 2 输入边起点(序号表示,每个序号回车,起点-1结束) 3 4 输入边起点(序号表示,每个序号回车,起点-1结束) 2 4 输入边起点(序号表示,每个序号回车,起点-1结束) -1 0 顶点信息:v0 v1 v2 v3 v4 邻接矩阵: 0 1 0 1 1 0 0 1 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0
关于带权图,稍作修改即可。
1、邻接表:边表节点添加一个权值字段即可(可以用元组实现,也可以用类实现);
2、邻接矩阵:无穷可以用一个极大值表示;权值直接填入对应位置即可。