I have doubly circular linked list
struct Element {
int data;
Element *next;
Element *previous;
};
struct List {
Element *head;
};
The task is to delete elements/nodes with the same data. For example, if the list has 1,1,3,4,5,1 and after parsing the function value=1 it should be as following 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;
Above is function which itterates through elements, finds element with given value/data and calls the following function to delete element.
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;
}
I have tried different ways but it always gave me errors. The problem is in relinking tail and head, as I think but I can't find the way to fix it.
The problem was in few relinking operations
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;
}
And as Marek Fekete noticed I didn't change iterating pointer each time I deleted an element. So I just iterated through all list from the beginning, each time I deleted an element.
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;
}
I think you can streamline it. Handling the removing tail/head/middle situations in removeElement
differently is not needed, with the only extra of resetting the list's head when removing the former head. I would rather put determining the next element in list and last item removal detection. Like this:
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;
}
Then you do not have to re-iterate from the head each tiem you remove an element and you do not have to handle the single item list as a special case:
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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.