【问题标题】:Java / Searching, modifying and removing elements from Array List of user defined classesJava / 从用户定义类的数组列表中搜索、修改和删除元素
【发布时间】:2019-09-21 17:39:47
【问题描述】:

我有一个有向图边的数组列表。

List<Edge> graph = new ArrayList();

我知道我可以将HashMap&lt;Integer, List&lt;Integer&gt;&gt; 用于有向图的邻接列表表示,以获得更快的 O(n) 性能,但 List&lt;Edge&gt; 只是澄清我对其他类似用户定义对象数组列表的问题的一个示例。

Edge 是用户定义的类如下:

public class Edge
{
    int sourceVertex;
    int destinationVertex;

    public int getSourceVertex()
    {
        return sourceVertex;
    }

    public int getDestinationVertex()
    {
        return destinationVertex;
    }

    public void setSourceVertex(int sourceVertex)
    {
        this.sourceVertex = sourceVertex;
    }

    public void setDestinationVertex(int destinationVertex)
    {
        this.destinationVertex = destinationVertex;
    }
}

我们可以通过创建边类的新对象来向有向图 Array List 添加新元素。

Edge edge = new Edge();
edge.setSourceVertex(1);
edge.setDestinationVertex(2);
graph.add(edge);

我的问题是,是否可以仅通过指定源顶点和目标顶点来从有向图 Array List 中搜索、修改或删除元素,而无需检查 Array List 的每个元素。我们不知道有向图 Array List 中任何特定元素的索引,以便能够通过索引在有向图 Array List 中执行这些操作。

如果我被允许仅使用有向图边的 Array List 表示,是否至少可以在 O(log n) 时间内完成这些搜索和修改操作,而无需花费 O(n) 时间?

【问题讨论】:

    标签: java search arraylist graph-theory getter-setter


    【解决方案1】:

    通过二分搜索始终可以在 O(log n) 时间内进行搜索。 从列表的中间开始,如果属性值比你想找的小或大,那么就剪到这里,走到左边或右边的一半。

    粗略的轮廓

    您将需要列表中的某种顺序来实现 O(log n) 性能。 像这样的东西: 按源排序,然后按目标排序:

    {
        // all with source=1
        Edge(src=1, target=1),
        Edge(src=1, target=2),
        Edge(src=1, target=4),
        // all with source=2
        Edge(src=2, target=2),
        // all with source=3
        Edge(src=3, target=2),
        // all with source=4
        Edge(src=4, target=2)
    }
    

    通过二分搜索可以找到具有指定 src 的特定边。但是如果你想搜索一个特定的目标,那么这将不起作用,因为列表是按源排序的——你必须重新排序! (见底部)。

    要在 O(log n) 时间内在正确的索引上插入边,也可以使用二分查找,然后通过插入新边

    graph.add(index, edge); 
    

    如果您想获取具有特定目的地的所有边,那么您必须重新排序 arrayList(它需要 O(log n) 并使用像 Mergesort 或 Heapsort 这样的良好排序算法),然后您可以执行相同的操作以上。

    通过以下方式重新排序您的数组:

    Collections.sort(arrayList, 
                            (o1, o2) -> o1.getDestination().compareTo(o2.getDestination()));
    

    ...或您想要排序的任何属性。

    【讨论】:

      【解决方案2】:

      您是否考虑过使用HashMap&lt;Integer, Set&lt;Integer&gt;&gt; 作为图表的表示形式?

      或者,您可以将equals()hashCode() 方法添加到您的Edge 类中,并使用Set&lt;Edge&gt; edges = new HashSet&lt;&gt;(); 之类的方法以及Java 中Set 接口中的标准方法。

      所有操作(添加/删除边)都将使用O(1) 运行时复杂度。

      【讨论】:

      • 是的,但我的问题不是关于任何给定图形的有效表示,而是我们如何有效地搜索、修改或删除用户定义类的数组列表(或哈希集)中的元素用户定义类中的变量值。
      • 我只是以图形为例来指定一个用户定义的类来问我的问题,但它也可以是其他一些用户定义的类。可能是图论标签可能与我提出的问题不够相关。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-14
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      相关资源
      最近更新 更多