多次优化递归双链表删除节点

时间:2011-07-22 18:55:04

标签: c++

我编写了一个递归的双向链接C ++函数来删除具有特定值的双向链表中的所有节点。有可能优化这个吗?谢谢。

struct marynode {
    int value;
    marynode* next;
    marynode* prev;
};

void DoubleLinkedListDeleteMultiple(marynode*& llist, int value){
    marynode* tmp = llist;

    if (llist == NULL)
        return;

    if (llist->value == value){
            DoubleLinkedListDeleteMultiple(llist->next, value); 
            if (llist->next == NULL){
                marynode* prev = llist->prev;
                delete llist;
                llist = NULL;
                llist = prev;
                if (llist)
                    llist->next = 0;
            }   
            else if (llist->prev == NULL){
                marynode* next = llist->next;
                delete llist;
                llist = NULL;
                llist = next;
                if (llist)
                    llist->prev = 0;
            }   
            else{
                marynode *x = llist;
                marynode  *mynext = x->next;
                while (x){
                    if (x->value == value){
                        marynode* clara = x->next;
                        marynode* zprev = x->prev;
                        delete x;
                        x = NULL;
                        x = clara;
                        llist = clara;
                        if (llist)
                            llist->prev = zprev;
                    }
                    else {
                        x = mynext;
                    }   
                    if (mynext){
                        mynext = mynext->next;
                    }
                }

            }
    }
    else{
            DoubleLinkedListDeleteMultiple(llist->next, value); 
    }
}

4 个答案:

答案 0 :(得分:1)

std :: list有什么问题吗?

另外,结构+全局函数?您可能希望使用面向对象的构造,例如成员方法。

为了优化这个特定的代码,我会将你的递归调用改为while循环。

while(llist != NULL) {
     if(llist->value == value) {
          if(llist->prev) {
              llist->prev->next = llist->next;
          }
          if(llist->next) {
              llist->next->prev = llist->prev;
          }
          node* next = llist->next;
          delete llist;
          llist = next;
     } else {
         llist = llist->next;
     }
}

答案 1 :(得分:1)

这看起来有点过分......为什么不只是迭代列表只保留好节点?

void DoubleLinkedListDeleteMultiple(marynode*& llist, int value)
{
    marynode *newfirst = NULL, *newlast = NULL;
    for (marynode *n=llist,*nn; n!=NULL; n=nn)
    {
        nn = n->next;
        if (n->value == value)
        {
            // Kill it
            delete n;
        }
        else
        {
            // Append at end of new list
            n->prev = newlast; n->next = NULL;
            if (newfirst == NULL) newfirst = n;
            if (newlast) newlast->next = n;
            newlast = n;
        }
    }
    llist = newfirst;
}

修改

如果必须删除大多数元素,上面的代码非常有效,但是如果相反删除的元素很少(因为使用相同的节点重建整个列表),则会进行大量的指针调整。如果用例相反,最好只是迭代节点并使用如下所示的循环删除坏节点

void DoubleLinkedListDeleteMultiple(marynode*& llist, int value)
{
    marynode *prev = NULL;
    marynode *n = llist;
    while (n)
    {
        if (n->value == value)
        {
            // Kill it
            marynode *nn = n->next;
            delete n;
            n = nn;
            // Fix links
            if (prev) prev->next = n; else llist = n;
            if (n) n->prev = prev;
        }
        else
        {
            // Move over to next one
            prev = n; n = n->next;
        }
    }
}

编辑2

另一种选择是尝试针对这两种极端情况进行优化,基本上是使用最紧密的循环复制或删除“运行”中的元素,并且只在运行结束时执行最终需要的修复...

void DoubleLinkedListDeleteMultiple(marynode *& list, int value)
{
    marynode *n = list;
    marynode *prev = NULL;
    while (n)
    {
        if (n->value == value)
        {
            // bad element: delete it and all following
            // consecutive bad elements
            do {
                marynode *nn = n->next;
                delete n;
                n = nn;
            } while (n && n->value == value);

            // fix the links only once per run
            if (prev) prev->next = n; else list = n;
            if (n) n->prev = prev;
        }
        else
        {
            // good element; just skip this and all
            // following good elements
            do {
                prev = n;
                n = n->next;
            } while (n && n->value != value);
        }
    }
}

警告:所有呈现的代码都未经过测试(甚至尚未编译......)

答案 2 :(得分:1)

为什么不在那里进行一些重构并提取你想要完成的事情的本质?

类似(未经测试且未编译)

void dll_link_nodes(node * theFirstNode, node *theNextNode){
    theFirstNode->next = theNextNode;
    theNextNode->prev = theFirstNode;
}

void dll_delete_node( marynode * theNode ){
    dll_link_nodes(theNode->prev, theNode->next);
    delete theNode;
}

node* dll_get_next_node (node* theNode){
    return theNode != NULL ? theNode->next : NULL;
}

inline int dll_node_get_value(node *n){
    return n->value;
}

void DoubleLinkedListDeleteMultiple(node*& llist, int value){
     node * iter = llist;

     while (iter != NULL){
         if ( dll_node_get_value(iter) == value) {
            node * target = iter;
            iter = dll_get_next_node(iter);
            dll_delete_node(target);
         }else
         {
             iter = dll_get_next_node(iter);
         }
     }

}

答案 3 :(得分:0)

早上好,昨晚我找到了一种方法,通过更改2行来优化DoublyLinkedListDeleteMultiple的C ++递归实现(请参阅//优化)。感谢大家的回答和评论。

void DoubleLinkedListDeleteMultiple(marynode *& llist,int value){     marynode * tmp = llist;

if (llist == NULL)
    return;

if (llist->value == value){
        DoubleLinkedListDeleteMultiple(llist->next, value); 
        if (llist->next == NULL){
            marynode* prev = llist->prev;
            delete llist;
            llist = NULL;
            llist = prev;
            if (llist)
                llist->next = 0;
        }   
        else if (llist->prev == NULL){
            marynode* next = llist->next;
            delete llist;
            llist = NULL;
            llist = next;
            if (llist)
                llist->prev = 0;
        }   
        else{
            marynode *x = llist;
            marynode  *mynext = x->next;
            int counter(0);
            while (x && counter++ < 1){               // Optimization
                if (x->value == value){
                    marynode* clara = x->next;
                    marynode* zprev = x->prev;
                    delete x;
                    x = NULL;
                    x = clara;
                    llist = clara;
                    if (llist)
                        llist->prev = zprev;
                }
                else {
                    x = mynext;
                }   
                if (mynext){
                    mynext = mynext->next;
                }
            }

        }
}
else{
        DoubleLinkedListDeleteMultiple(llist->next, value); 
}

}