《算法之美》の链表问题のremoveHead中的缺陷

问题:

发现并修复下面C/C++函数中的缺陷,该函数是想从一个单向链表中删除头元素。

void removeHead(Node *head)

{

         delete head;

         head = head->next;

}

 

解答:缺陷发现策略:对于拿到的任何函数,考虑下面4个常见的问题:

1)检查数据是否正确地进入了该函数;

2)检查函数的每一行是否能正确工作;

3)检查该函数的输出数据是否正确;

4)检查常见的错误情况,如以指针为参数的函数在传入空指针时会失败。

 

函数释放了head之后,有对head进行引用,错误;我们试着将这两行颠倒位置,就会导致head之后的元素被删除,而不是head。因此正确的方法是利用一个临时变量:

void removeHead(Node *head)

{

         Node *tmp = head->next;

         delete head;

         head = tmp;

}

 

现在我们进行上面策略的第三步,即确保函数返回正确的值,可以看出,这个函数尽管没有显式地返回值,但却有隐式的返回值。这个函数支持对head指针进行更新。在C语言中,所有参数都是按值传递的,所以函数会得到每一个参数的本地拷贝,而对本地拷贝的任何修改都不会对函数体之外产生影响。即上面代码第三行对head赋的任何新值都不会有效。要修复这个缺陷,我们需要一种能修改调用代码中head指针的方法。在C语言中,变量不能按引用传递,所以解决方案就是传递一个我们想修改的变量的指针,也就是head指针的指针,改动后,代码如下:

void removeHead(Node **head)

{

         Node *tmp = (*head)->next;

         delete *head;

         *head = tmp;

}

 

接下来,我们检查边界条件。在只有1个元素的链表中,这个函数能正常工作,它删除了这个元素并将head指针设为了NULL。在0个元素的链表中,这个链表本身就是一个NULL指针,因此,head指针是NULL,上面代码中第一行错误地引用了NULL指针。因此,应该检查head指针是否为NULL,最终完善的函数如下:

void removeHead(Node **head)

{

         Node *tmp;

         if( !(*head) )

         {

                   tmp = (*head)->next;

                   delete *head;

                   *head = tmp;

         }

}

posted on 2010-05-23 16:53  android开发实例  阅读(201)  评论(0编辑  收藏  举报

导航