簡體   English   中英

從雙向循環鏈表中刪除所有具有相同值的元素

[英]Delete all elements with same value from doubly circular linked list

我有雙重循環鏈表

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

struct List {
    Element *head;
};

任務是刪除具有相同數據的元素/節點。 例如,如果列表具有1,1,3,4,5,1,並且在解析函數值= 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;

}

我嘗試了不同的方法,但是它總是給我帶來錯誤。 我認為問題在於重新連接尾巴和頭部,但找不到解決方法。

問題出在很少的重新鏈接操作中

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

我認為您可以簡化它。 不需要以不同的方式處理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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM