使用O(1)插入操作创建邻接列表

时间:2015-03-14 16:08:45

标签: c optimization data-structures time-complexity graph-theory

我现在所拥有的是:

void addEdge(listNode **adjacencyList, int firstVertex, int secondVertex, int cost) {
    if (firstVertex == secondVertex) return;

    attachNeighbor(firstVertex, cost, adjacencyList[secondVertex]);
    attachNeighbor(secondVertex, cost, adjacencyList[firstVertex]);
}

void attachNeighbor(int id, int cost, listNode *root) {
    if (root->vertex == 0) {
        root->vertex = id;
        root->cost = cost;
    } else {
        listNode *neighbor;
        neighbor = (listNode *) malloc(sizeof(listNode));
        neighbor->cost = cost;
        neighbor->vertex = id;

        listNode *next = root;
        while (next->next != NULL) {
            next = next->next;
        }

        next->next = neighbor;
    }
}
然而,对于10k +顶点和超过一百万个边缘,它真的很慢,因为每个插入操作都需要O(邻居数)。后来我对此只需要遍历所有邻居一次,所以我不需要快速检索。我想到了双向链表并保持指向最后一个节点的指针,然后当我不得不迭代时我会倒退,但我不知道如何在C中做到这一点

2 个答案:

答案 0 :(得分:2)

您可以将新节点放在列表的前面,每次更改根目录:

void addEdge(listNode **adjacencyList, int firstVertex, int secondVertex, int cost) {
    if (firstVertex == secondVertex) return;

    attachNeighbor(firstVertex, cost, adjacencyList + secondVertex);
    attachNeighbor(secondVertex, cost, adjacencyList + firstVertex);
}

void attachNeighbor(int id, int cost, listNode **pRoot) {
    listNode *root = *pRoot;
    if (root->vertex == 0) {
        root->vertex = id;
        root->cost = cost;
    } else {
        listNode *neighbor;
        neighbor = (listNode *) malloc(sizeof(listNode));
        neighbor->cost = cost;
        neighbor->vertex = id;
        neighbor->next = root;
        *pRoot = neighbor;
    }
}

答案 1 :(得分:1)

  

我想到了双向链表并保持指向最后一个节点的指针

您不需要双向链表,只需保留指向最后一个节点的指针即可。

创建第二个数组,比如adjacencyListEnd,并将指向其元素的指针传递给attachNeighbor

void attachNeighbor(int id, int cost, listNode *root, listNode **last) {
    if (root->vertex == 0) {
        root->vertex = id;
        root->cost = cost;
        *last = root;
    } else {
        listNode *neighbor;
        neighbor = (listNode *) malloc(sizeof(listNode));
        neighbor->cost = cost;
        neighbor->vertex = id;
        (*last)->next = neighbor;
        *last = neighbor;  
    }
}

你这样称呼它:

void addEdge(listNode **adjacencyList, int firstVertex, int secondVertex, int cost) {
    if (firstVertex == secondVertex) return;

    attachNeighbor(firstVertex, cost, adjacencyList[secondVertex], &adjacencyListEnd[secondVertex]);
    attachNeighbor(secondVertex, cost, adjacencyList[firstVertex], &adjacencyList[firstVertex]);
}