2014-09-26 172 views
0

我正在重构一些C代码,并且因为一段时间我挂断了与链接列表数据结构有关的问题。请看看下面简单的代码片段:删除链接列表中的元素

Link apply(Link first, pred_ptr cond) 
{ 
    Link t=first->next,p=first; 
    do{ 
     if(cond(t)) 
     { 
      p->next=t->next; 
      free(t); 
      t=p; 
     } 
     p=t; 
     t=t->next; 
    }while(t!=first); 
    //Check the first 
    if(cond(first)) 
    { 
     t=first->next; 
     free(first); 
     first=t; 
     p->next=t; 
    } 
    return first; 
} 

功能适用删除所有来自链表中的元素,其功能COND返回一个非零值。 链接是这样的:

struct node 
{ 
    struct node* next; 
    //Stuff 
}; 

typedef struct node* Link 

好了,我唯一的问题是关于如何所适用删除链表的第一个元素 - 第一 - ,看起来像额外的代码出来的循环是为了评估第一个元素所必需的,我没有能够把这个检查放在循环内没有额外的如果陈述,也许你可能知道如何从循环中删除额外的代码 - 如果可能 - 你会?

谢谢,

有一个愉快的一天。

回答

0

第一个元素是一个特殊情况,所以您将不会遇到与其他情况稍有不同的代码。所以你的选择是:(1)在你的例子中它的完成方式;(2)将特殊情况代码放在主循环中,并且每次迭代执行一次if比较;(3)使用指向指针的不太容易理解的版本。

你应该问自己的第一个问题是:你为什么要重构?为了清楚起见,还是因为需要更快的实施?要么 ...?

0

你的代码有逻辑差不多吧,但有一些地方的各种问题:

  • 读码,我猜测,link list确实是一个circular link list,因为如果不是,一些->next将是一些== NULL节点。并且代码在任何地方都不检查NULL,如t=t->next;之类的行在while循环结束之前会在达到NULL时执行未定义行为。假设cond功能工作正常与NULL并没有输入if声明(如果输入,UB将在这里执行p->next=t->next;)。如果link list只是一个link list而非循环,则代码需要大量重构。

在任一方式linked listcircular linked list的第一个元素可以被单独分析,在简单linked list是更好这样的情况下,因为环路分析节点的其余部分更具可读性和自由处理具体案件(将在循环中处理,并且不会过载分析另一个节点并检查第一个节点),在circular linked list的情况下,第一个元素可以在循环中进行优雅地分析,但可以在循环中进行分析太。

顺便说一句,你已经在重构,如果这是变量名称中使用的实际代码将得到更好的改善(p - >以前,t - >测试?我认为等...)

+0

谢谢,列表是循环的,一切正常,我唯一的担心是关于特定情况* cond(first)*的处理,但我怀疑为了可读性,我可能会保留代码,因为它是。 – fjanisze 2014-09-26 18:54:33