有向图的数据结构,允许快速删除节点?

时间:2011-02-22 21:51:17

标签: algorithm graph directed-graph

我需要存储有向图(不一定是非循环的),以便尽可能快地删除节点。我不介意存储额外的数据,以便确切地知道删除节点时必须经过哪些边缘。

如果我存储边缘列表(作为节点索引对),那么当杀死某个节点时,我必须在整个列表中搜索源或目标为n的边。这对我的申请来说太贵了。通过在节点中存储一些额外的数据可以避免这种搜索吗?

一个想法是让每个节点存储自己的源和目标,作为两个单独的列表。当节点n被杀死时,它的列表也被杀死。但是,与节点n相关联的所有目标/来源如何知道如何更新自己的列表(即,从其列表中消除已失效的节点)?这需要一些昂贵的搜索......

可以避免吗?

THX。

2 个答案:

答案 0 :(得分:4)

你有两个选择,而不是过于花哨的邻接列表和邻接矩阵。前者可能是你正在做的最好的。要删除节点,只需删除该节点的所有外边缘列表。对于in-edge,您可以考虑为O(1)查找的每个列表保留一个哈希表。

这是一个很好的概述 http://www.algorithmist.com/index.php/Graph_data_structures

答案 1 :(得分:2)

我解决了!这是无向图的解决方案,之后添加方向很容易。

在每个顶点我都有一个特殊的邻接列表。它是一个列表(双链接,便于插入/删除),其元素是“插槽”:

class Slot {
  Slot prev, next; // pointers to the other slots in the list
  Slot other_end; // the other end of the edge: not a vertex, but a Slot!
  Vertex other_vertex; // the actual vertex at the other end

  void kill() {
    if (next!=null) next.kill(); // recursion
    other_end.pop_out();
  }

  void pop_out() {
    if (next!=null) next.prev = prev;
    if (prev!=null) prev.next = next;
    else other_end.other_vertex.slot_list = next; // in case this slot is the
                                                  // first in its list, I need
                                                  // to adjust the vertex's
                                                  // slot_list pointer.
    // other_end.other_vertex is actually the vertex to which this slot belongs;
    // but this slot doesn't know it, so I have to go around like this.
  }

}

所以基本上每个边都由两个槽代表,彼此交叉指向。每个顶点都有一个这样的插槽列表。

当一个顶点被杀死时,它会在其槽列表中递归地发送一个“kill”信号。每个插槽都会通过销毁其other_end(从邻居列表中匆匆弹出,修复后面的上一个/下一个指针)来响应。

这样就可以删除顶点及其所有边,而无需任何搜索。我需要支付的价格是内存:而不是3个指针(普通,双向链接邻接列表的上一个,下一个和顶点),我必须保留4个指针(prev,next,vertex和other_end)。

这是基本的想法。对于有向图,我只需要以某种方式区分IN插槽和OUT插槽。可能将每个顶点的邻接列表分成两个单独的列表:IN_slot_list和OUT_slot_list。