循环通过LinkedList时读取访问冲突

时间:2017-01-06 09:14:57

标签: c++

我正在创建一个行星模拟,它利用双向链表和几个循环来计算力,碰撞等。我遇到的问题是在尝试由于碰撞而删除行星时出现读取访问冲突错误。

当检查碰撞时,两个行星中较小的一个被删除,而我写它的方式是等式中较小的行星可以来自包围循环,如果删除则会破坏循环。

C的新成员;现在几天盯着同一个问题;并且我的班级讲师让我们使用C / C ++混合,导致我努力想到一个有效的方法来解决这个问题。将循环移出可以并且已经解决了问题,但是对模拟的性能产生了极大的影响。

代码如下:

struct planet *head; //Head of list
struct planet *tail; //Tail of list

struct planet { 
    //Data
    float mass;
    struct planet *next;
    struct planet *prev;
};

planet *remove(struct planet* p) {//Breaking the tree
    if (p == head) {
        removeHead(); //Method not included in sample due to size and it is sound.
    }
    else if (p == tail) {
        removeTail();//Method not included in sample due to size and it is sound.
    }
    else {
        p->prev->next = p->next;
        p->next->prev = p->prev;
    }
    return p;
}

planet *destroy(struct planet* p) {
    if (p) {
        if (p != head || p != tail || (!p->next && p->prev)) {
            delete p;
            printf("Deleted\n");
            return 0;
        }
        else {
            printf("Not deleted\n");
            return 0;
        }
     }
 }

for (struct planet *p1 = head; p1 != 0; p1 = p1->next)
    {
        for (struct planet *p3 = head; p3 != 0; p3 = p3->next)
            {
                //Collision logic
                if(p1 != p3){
                     if(p1->mass >= p3->mass){
                        destroy(remove(p3)); //Does not cause an error
                        break;
                     }else{
                        destroy(remove(p1)); //Causes the error.
                        break;
                        //Deleting p1 here means the for loop can't move on
                     } 
                }
            }
    }

我正在寻找的是关于如何有效地删除p1而不破坏循环的一些建议。

非常感谢任何帮助,请原谅我不太干净的代码。

1 个答案:

答案 0 :(得分:2)

p1被销毁时突破内部循环,不会破坏外部循环,其中p1在被删除后被循环控件取消引用。

你可以使用这样的代码来避免它。我不喜欢将for循环与链表一起使用,while可以轻松设置下一个链接。

struct planet *p1link, *p3link;

p1 = head;
while(p1 != NULL) {
    p1link = p1->next;              // collect next link now
    p3 = p1->next;                  // avoid detecting B-A as well as A-B
    while(p3 != NULL) {
        p3link = p3->next;          // collect next link now
        //Collision logic
        if(p1->mass >= p3->mass){
            destroy(remove(p3));
        } else {
            destroy(remove(p1));
        }
        p3 = p3link;                // next
    }
    p1 = p1link;                    // next
}    

然而,整个概念存在缺陷,因为您删除的p3可能是下一个p1行星。因此,我建议包含一个结构成员pending,然后再对该列表进行另一次解析,以删除死行星。