从双向循环链表中删除具有相同值的所有元素
Delete all elements with same value from doubly circular linked list
我有双向循环链表
struct Element {
int data;
Element *next;
Element *previous;
};
struct List {
Element *head;
};
任务是删除具有相同数据的elements/nodes。例如,如果列表有 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;
以上是遍历元素的函数,找到给定 value/data 的元素并调用以下函数删除元素。
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
中删除 tail/head/middle 的情况,唯一的额外操作是在删除前一个头部时重置列表的头部。我宁愿确定列表中的下一个元素和最后一项删除检测。像这样:
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;
}
我有双向循环链表
struct Element {
int data;
Element *next;
Element *previous;
};
struct List {
Element *head;
};
任务是删除具有相同数据的elements/nodes。例如,如果列表有 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;
以上是遍历元素的函数,找到给定 value/data 的元素并调用以下函数删除元素。
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
中删除 tail/head/middle 的情况,唯一的额外操作是在删除前一个头部时重置列表的头部。我宁愿确定列表中的下一个元素和最后一项删除检测。像这样:
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;
}