【问题标题】:Creating adjacency list with O(1) insert operation使用 O(1) 插入操作创建邻接表
【发布时间】:2015-03-14 16:08:45
【问题描述】:

我目前拥有的是这样的:

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+ 个顶点和超过 100 万条边,它真的很慢,因为每个插入操作都需要 O(邻居数)。后来我要做的只是遍历所有邻居一次,所以我不需要快速检索。我考虑过双向链表并保持指向最后一个节点的指针,然后当我必须迭代时,我会倒退,但我不知道如何在 C 中做到这一点

【问题讨论】:

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


【解决方案1】:

你可以把新节点放在列表的前面,每次都换根:

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;
    }
}

【讨论】:

  • 该死的,我得刷新我的算法技能:) 谢谢
【解决方案2】:

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

你不需要一个双向链表,你只需要一个指向最后一个节点的指针。

创建第二个数组,例如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]);
}

【讨论】:

    猜你喜欢
    • 2022-01-23
    • 2017-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多