6.1.3 图的基本操作
//Graph node class
public class GraphNode<T>
{
public T Value { get; set; }
public GraphNode(T value)
{
Value = value;
}
}
//Actions of graph
public interface IGraph<T>
{
int NodeNum { get; }
int EdageNum { get; }
int IsNode(GraphNode<T> node);
bool SetNode(GraphNode<T> node);
bool DelNode(GraphNode<T> node);
bool SetEdge(GraphNode<T> node1, GraphNode<T> node2, int value);
bool DelEdge(GraphNode<T> node1, GraphNode<T> node2);
bool IsEdge(GraphNode<T> node1, GraphNode<T> node2);
}
6.2 图的存储结构
6.2.1 邻接矩阵
邻接矩阵用两个数组来表示图,一个数组是一维数组,存储图中顶点的信息,一个数组是二维数组,即矩阵,存储顶点之间的信息。
public class GraphMatrix<T> : IGraph<T>
{
private GraphNode<T>[] nodeArray;
private int[,] edageArray;
public int NodeNum { get; private set; }
public int EdageNum { get; private set; }
public GraphMatrix(int length)
{
nodeArray = new GraphNode<T>[length];
edageArray = new int[length, length];
}
public int IsNode(GraphNode<T> node)
{
for (int i = 0; i < NodeNum; i++)
{
if (node == nodeArray[i])
return i;
}
return -1;
}
public bool SetNode(GraphNode<T> node)
{
if (NodeNum >= nodeArray.Length)
return false;
//If the node is already in the array, return false
if (IsNode(node) != -1)
return false;
nodeArray[NodeNum] = node;
NodeNum++;
return true;
}
public bool DelNode(GraphNode<T> node)
{
int index = IsNode(node);
//If the node was not in node array, return false
if (index == -1)
return false;
//move the last node to the deleted node option
nodeArray[index] = nodeArray[NodeNum - 1];
for (int i = 0; i < NodeNum; i++)
{
if (edageArray[index, i] != 0)
EdageNum -= 1;
if (edageArray[i, index] != 0)
EdageNum -= 1;
edageArray[index, i] = edageArray[NodeNum - 1, i];
edageArray[i, index] = edageArray[i, NodeNum - 1];
}
edageArray[index, index] = 0;
for (int i = 0; i < NodeNum; i++)
{
if (edageArray[NodeNum - 1, i] != 0)
edageArray[NodeNum - 1, i] = 0;
if (edageArray[i, NodeNum - 1] != 0)
edageArray[i, NodeNum - 1] = 0;
}
NodeNum -= 1;
return true;
}
public bool SetEdge(GraphNode<T> node1, GraphNode<T> node2, int value)
{
int index1 = IsNode(node1);
int index2 = IsNode(node2);
//Input node was not exist in node array
if (index1 == -1 || index2 == -1)
return false;
if (edageArray[index1, index2] == 0)
EdageNum += 1;
edageArray[index1, index2] = value;
return true;
}
public bool DelEdge(GraphNode<T> node1, GraphNode<T> node2)
{
int index1 = IsNode(node1);
int index2 = IsNode(node2);
//Input node was not exist in node array
if (index1 == -1 || index2 == -1)
return false;
if (edageArray[index1, index2] != 0)
{
EdageNum -= 1;
edageArray[index1, index2] = 0;
return true;
}
else
//There is no edage between the two input nodes
return false;
}
public bool IsEdge(GraphNode<T> node1, GraphNode<T> node2)
{
int index1 = IsNode(node1);
int index2 = IsNode(node2);
//The input node was not in the node array
if (index1 == -1 || index2 == -1)
return false;
if (edageArray[index1, index2] != 0)
return true;
else
return false;
}
public void PrintMatrix()
{
Console.Write(" ");
for (int i = 0; i < NodeNum; i++)
{
if (i == 0)
Console.Write("| ");
Console.Write(nodeArray[i].Value);
Console.Write(" ");
}
Console.WriteLine();
Console.WriteLine("--+" + string.Empty.PadRight((NodeNum + 1) * 2, '-'));
for (int i = 0; i < NodeNum; i++)
{
Console.Write(nodeArray[i].Value);
Console.Write(" ");
for (int j = 0; j < NodeNum; j++)
{
if (j == 0)
Console.Write("| ");
Console.Write(edageArray[i, j]);
Console.Write(" ");
}
Console.WriteLine();
Console.WriteLine(" |");
}
}
}
邻接矩阵类型的测试:
using GraphObject;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
GraphMatrix<int> matrix = new GraphMatrix<int>(100);
//Inial graph object
GraphNode<int> node1 = new GraphNode<int>(1);
GraphNode<int> node2 = new GraphNode<int>(2);
GraphNode<int> node3 = new GraphNode<int>(3);
GraphNode<int> node4 = new GraphNode<int>(4);
GraphNode<int> node5 = new GraphNode<int>(5);
GraphNode<int> node6 = new GraphNode<int>(6);
GraphNode<int> node7 = new GraphNode<int>(7);
GraphNode<int> node8 = new GraphNode<int>(8);
matrix.SetNode(node1);
matrix.SetNode(node2);
matrix.SetNode(node3);
matrix.SetNode(node4);
matrix.SetNode(node5);
matrix.SetNode(node6);
matrix.SetNode(node7);
matrix.SetNode(node8);
matrix.SetEdge(node2, node1, 2);
matrix.SetEdge(node3, node1, 3);
matrix.SetEdge(node2, node3, 4);
matrix.SetEdge(node3, node4, 5);
matrix.SetEdge(node5, node6, 4);
matrix.SetEdge(node8, node6, 1);
Assert.AreEqual<int>(8, matrix.NodeNum);
Assert.AreEqual<int>(6, matrix.EdageNum);
//Scenario 1: Test add new node
GraphNode<int> node9 = new GraphNode<int>(9);
matrix.SetNode(node9);
matrix.SetEdge(node9, node5, 3);
matrix.SetEdge(node9, node8, 1);
matrix.SetEdge(node6, node9, 2);
Assert.AreEqual<int>(9, matrix.NodeNum);
Assert.AreEqual<int>(9, matrix.EdageNum);
//Scenario 2: Test remove node
matrix.DelNode(node8);
Assert.AreEqual<int>(8, matrix.NodeNum);
Assert.AreEqual<int>(7, matrix.EdageNum);
matrix.SetNode(node8);
matrix.SetEdge(node8, node6, 1);
matrix.SetEdge(node9, node8, 1);
Assert.AreEqual<int>(9, matrix.NodeNum);
Assert.AreEqual<int>(9, matrix.EdageNum);
//Scenario 3: Test add/remove new edage
matrix.DelEdge(node3, node4);
Assert.AreEqual<int>(9, matrix.NodeNum);
Assert.AreEqual<int>(8, matrix.EdageNum);
matrix.SetEdge(node3, node4, 5);
Assert.AreEqual<int>(9, matrix.NodeNum);
Assert.AreEqual<int>(9, matrix.EdageNum);
//Scenario 4: Other medthods
Assert.IsTrue(matrix.IsNode(node4) >= 0, "node4 should be exist in matrix");
Assert.IsFalse(matrix.IsNode(new GraphNode<int>(10)) >= 0, "node4 should not be exist in matrix");
Assert.IsTrue(matrix.IsEdge(node3, node1), "edage should be exist in matrix");
Assert.IsFalse(matrix.IsEdge(node3, node2), "edage should not be exist in matrix");
}
}
}
邻接矩阵存储图的类的模型图:
邻接矩阵存储图的类的关系图: