c# - 检查链表是否> 包含某个节点
问题描述
我正在使用 c# 实现一个 Graph 并且我想检查我是否两次插入了相同的边缘,以便我可以在这样做时抛出异常。
我的班级名称是 Graph
这是我的 _adjacencyList 声明
protected virtual Dictionary<T, LinkedList<Node<T>>> _adjacencyList { get; set; }
这是我的节点类
class Node<T> where T : IComparable<T>
{
public double speed { get; set; }
public double time { get; set; }
public double distance { get; set; }
public T source { get; set; }
public T destenation { get; set; }
public Node() { }
public Node(T SOURCE, T DESTENATION, double SPEED, double DISTANCE)
{
this.source = SOURCE;
this.destenation = DESTENATION;
this.speed = SPEED;
this.distance = DISTANCE;
this.time = this.distance / this.speed;
}
}
这是我的 addEdge 函数,它采用源顶点和目标顶点以及边缘的值“权重”
public void addEdge(T source, T Destenation, double speed, double Distance)
{
if (_adjacencyList.Count <= 0)
{
throw new InvalidOperationException("addEdge: There are no Vertices in Graph.\n");
}
else
{
if (_adjacencyList.ContainsKey(source) && _adjacencyList.ContainsKey(Destenation))
{
var sourceEdge = new Node<T>(source, Destenation, speed, Distance);
var destenationEdge = new Node<T>(Destenation, source, speed, Distance);
if (_adjacencyList[source].Contains(sourceEdge) || _adjacencyList[Destenation].Contains(destenationEdge))
{
throw new InvalidOperationException("addEdge: Edge already exists in Graph.\n");
}
else
{
_adjacencyList[source].AddLast(sourceEdge);
_adjacencyList[Destenation].AddLast(destenationEdge);
++_edgeCount;
}
}
else
{
throw new NullReferenceException("addEdge : Source or Destenation Vetrtex Don't Exist in Graph.\n");
}
}
}
当我在 main 中编写此代码时,它不会抛出“Edge 已存在于 Graph 中”的异常。
Graph<int> g = new Graph<int>();
g.addVertex(1);
g.addVertex(2);
g.addVertex(3);
g.addVertex(4);
g.addEdge(1,2,15.0,60.0);//Multiple Edge
g.addEdge(1, 2, 15.0, 60.0);//Multiple Edge
g.addEdge(1, 3, 5.0, 40.0);
g.addEdge(2,3,1.0,10.0);
g.addEdge(4,1,2.0,8.0);
我的实施有什么问题以及如何解决?
解决方案
发生这种情况是因为您忘记覆盖Equals
class 的方法Node
。
您需要以下实现:
public class Edge<T>
{
public double Speed { get; }
public double Time { get; }
public double Distance { get; }
public T Source { get; }
public T Destination { get; }
public Edge(T source, T destination, double speed, double distance)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (destination == null) throw new ArgumentNullException(nameof(destination));
if (Math.Abs(speed) < 1E-9) throw new ArgumentException("speed must greater than zero", nameof(speed));
if (Math.Abs(distance) < 1E-9) throw new ArgumentException("distance must greater than zero", nameof(speed));
Source = source;
Destination = destination;
Speed = speed;
Distance = distance;
Time = Distance / Speed;
}
public override bool Equals(object obj)
{
if (!(obj is Edge<T> objAsEdgeT))
{
return false;
}
return Math.Abs(Speed - objAsNodeT.Speed) < 1E-9
&& Math.Abs(Time - objAsNodeT.Time) < 1E-9
&& Source.Equals(objAsNodeT.Source)
&& Destination.Equals(objAsNodeT.Destination);
}
public override int GetHashCode()
{
unchecked
{
int hash = 13;
hash = (hash*7) + Speed.GetHashCode();
hash = (hash*7) + Time.GetHashCode();
hash = (hash*7) + Source.GetHashCode();
hash = (hash*7) + Destination.GetHashCode();
return hash;
}
}
}
一些注意事项:
- 命名至关重要。类
Node
本质上代表一条边。所以这Edge
将是一个更合适的类名。反过来想想,对于一个人来说,阅读并真正理解一段与图节点相关的代码会有多困难,而我们选择的名称是边。 - 尝试使用常见的编码样式,以使您的代码更具可读性。例如,对于我们使用Pascal Case的属性。
- 在这种情况下,您不需要公共设置器。
- 您不需要默认构造函数。有人打电话是什么意思
new Edge<int>()
?更不用说你会得到一个例外,因为所有属性都会获得相应的默认值(双 -> 0),并且除法距离/速度将导致除法为零...... - 在构造函数内部,我们必须验证我们得到的值是否有意义。否则,我们最多只会有一个处于无意义状态的对象。没有节点我们就没有边!因此
null
对于源和目标都不是有效值。此外distance
,并且speed
应该大于零。即使speed
有一些意义,和的划分distance
也speed
将毫无意义——更不用说例外了……
推荐阅读
- html - 如何在 Bootstrap 中将按钮对齐到文本框的右侧
- ilmerge - 将多个 dll 合并到插件项目中时出现 ILMERGE 错误
- android - 使用 React Native 更改键盘后面的背景颜色?
- r - For 循环在 R 的 gsub 中使用的项目列表
- facebook-login - 如何在 Google AMP 中实现 Google 和 Facebook 的登录按钮?
- codenameone - codenameone QR/条形码扫描仪是否可以在模拟器上工作?
- java - 将 Jersey 客户端转换为 HttpUrlConnection
- html - 将 Bootstrap 的 Modal 上的 X 按钮更改为左侧
- javascript - 在 reducer 函数中更改 targetArray.length 时的 targetArray.reduce 行为
- python - Django-Rest:需要从 oracle 批量获取所有数据