【问题标题】:Delete all elements with same value from doubly circular linked list从双循环链表中删除所有具有相同值的元素
【发布时间】:2017-03-28 20:08:42
【问题描述】:

我有双循环链表

struct Element {
    int data;
    Element *next;
    Element *previous;
};

struct List {
    Element *head;
};

任务是删除具有相同数据的元素/节点。例如,如果列表有 1,1,3,4,5,1,解析函数 value=1 后应该如下 3,4,5。

bool removeAllValue(List &l, int value) {
    if(!l.head)
        return false;
    else if(l.head->next == l.head && l.head->data == value){
        l.head = NULL;
        return true;
    }
    Element *p = l.head;
    do{
        if(p->data == value)
            removeElement(l, p);
        p = p->next;
    }while(p!=l.head);
    return true;

上面是遍历元素的函数,找到具有给定值/数据的元素并调用以下函数删除元素。

void removeElement(List &l, Element *element){
    Element *previous = element->previous;
    Element *next = element->next;
    Element *head = l.head;
    if(next == head){ //if element is tail of the list
        l.head->previous = element->previous; // relinking head's previous to new tail
        element->previous->next = head;
    }else if(element == head){ // if element is head of the list
        l.head = next; // relinking head to tail
        l.head->previous = previous; // relinking tail to head
    }else{
        previous->next = next;
        next->previous = previous;
    }
    delete element;

}

我尝试了不同的方法,但它总是给我错误。问题在于重新连接尾部和头部,我认为但我找不到修复它的方法。

【问题讨论】:

  • 第一种情况(元素是尾巴)看起来很奇怪。在这种情况下,你为什么要调整 head->next 呢?为什么tail的前一个指向头部?
  • @MarekFekete 谢谢。改成关注l.head->previous = element->previous; element->previous->next = head;
  • 看起来更好。有帮助吗?
  • @MarekFekete 不,如果列表是 1,2,1,1 在它给出 2,1,1,0 的函数之后。
  • 另外一个问题是你在removeElement中做了delete element,然后在调用函数中仍然使用它(p=p->next)。

标签: c++ data-structures doubly-linked-list


【解决方案1】:

我认为您可以简化它。不需要以不同的方式处理removeElement 中的删除尾部/头部/中间情况,唯一额外的就是在删除前一个头部时重置列表的头部。我宁愿确定列表中的下一个元素和最后一项删除检测。像这样:

Element* removeElement(List &l, Element *element) {
    Element *newnext;
    Element *previous = element->previous;
    Element *next = element->next;
    Element *head = l.head;

    previous->next = next;
    next->previous = previous;
    newnext = next;

    if (element == head) { // if element is head of the list
        l.head = next; // set the head correctly
    }

    if (element == newnext)  // detect if last element in the list was deleted
        l.head = newnext = nullptr;
    else if (newnext == head) // detect if next is at the head again
        newnext = nullptr;

    delete element;
    return newnext;
}

然后,您不必在每次删除元素时从头部重新迭代,并且您不必将单个项目列表作为特殊情况处理:

bool removeAllValue(List &l, int value) {
    if (!l.head)
        return false;

    Element *p = l.head;
    do {
        if (p->data == value)
        {
            p = removeElement(l, p);
        }
        else
        {
            p = p->next;
            if (p == l.head)
                p = nullptr;
        }
    } while (p);
    return true;
}

【讨论】:

    【解决方案2】:

    问题在于很少的重新链接操作

    void removeElement(List &l, Element *element){
        Element *previous = element->previous;
        Element *next = element->next;
        Element *head = l.head;
        if(element->next == element)
            l.head = NULL;
        else if(next == head){ //if element is tail of the list
            Element *newTail = previous;
            newTail->next = l.head;
            l.head->previous = newTail;
        }else if(element == head){ // if element is head of the list
            l.head = next; // relinking head
            l.head->previous = previous; // relinking tail to head
            previous->next = l.head; // relinking head to tail
        }else{
            previous->next = next;
            next->previous = previous;
        }
        delete element;
    }
    

    正如 Marek Fekete 注意到的那样,每次删除元素时我都没有更改迭代指针。所以我只是从头开始遍历所有列表,每次我删除一个元素。

    bool removeAllValue(List &l, int value) {
        if(!l.head)
            return false;
        else if(l.head->next == l.head && l.head->data == value){
            l.head = NULL;
            return true;
        }
        Element *p = l.head;
        bool end = false;
        while(!end){
            do{
                if(p->data == value){
                    Element *tmp = p;
                    p = p->next;
                    removeElement(l, tmp);
                    break;
                }else
                    p = p->next;
                if(p==l.head || l.head == NULL){
                    end = true;
                    break;
                }
            }while(p);
        }
        return true;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-22
      • 1970-01-01
      • 2017-07-29
      相关资源
      最近更新 更多