`
java-mans
  • 浏览: 11814044 次
文章分类
社区版块
存档分类
最新评论

《算法之美》の链表问题の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;

}

}

分享到:
评论

相关推荐

    c语言链表的排序算法-排序链表最快的算法是什么?.pdf

    为了解决这个问题,我们可以将链表复制到数组中,然后使用快速排序或合并排序来进行排序。这样做的好处是可以提高缓存的性能,从而提高排序算法的速度。 在我们的实验中,我们使用了C语言来实现链表排序算法,并...

    Java算法实例-双向链表操作

    双向链表与单链表相比,其独特之处在于每个节点不仅包含指向下一个节点的指针,还包含指向前一个节点的指针,这使得在链表中的前进和后退操作变得相对高效。 双向链表的操作主要包括创建、插入、删除、遍历等。下面...

    几种排序算法的实现(链表)

    在编程领域,排序算法是数据结构与算法中的基础部分,对于任何程序员来说,理解和掌握排序算法都是非常重要的。这里我们主要探讨的是使用链表实现的排序算法。链表是一种非连续、非顺序的存储结构,每个元素称为节点...

    数据结构的双链表算法

    双链表是数据结构中的一种重要类型,它在计算机科学中有着广泛的应用。与单链表相比,双链表的特点在于每个...通过理解和熟练掌握双链表及其算法,对于提升编程能力,尤其是解决复杂数据处理问题的能力,具有重要意义。

    算法__链表的操作

    在IT领域,特别是数据结构与算法的学习中,链表是一个非常基础且重要的概念。链表是一种线性数据结构,其中的元素不是存储在连续的内存空间中,而是通过指针链接在一起,每个元素称为节点,包含数据部分和指向下一个...

    Java算法(链表操作实例)

    在编程领域,算法是解决问题的关键,而链表作为一种基础数据结构,在实现各种复杂算法时扮演着重要角色。本文将深入探讨Java中链表的操作实例,旨在帮助开发者更好地理解和运用链表来解决实际问题。 首先,我们需要...

    算法-数据结构之链表合并算法.rar

    链表合并算法是数据结构与算法领域中的一个重要话题,它主要涉及到如何将两个或多个已排序的链表高效地合并成一个有序链表。在处理大量数据时,链表因其动态内存分配和高效的插入、删除操作,常被用于实现各种算法。...

    数据结构-基本算法-孩子兄弟链表

    数据结构-基本算法-孩子兄弟链表(学生时代源码,调试可运行)

    链表插入结点算法

    其中,插入节点是链表中最常见的操作之一。 #### 2. 插入节点的基本原理 插入节点的基本思想是在链表中的指定位置添加一个新的节点。根据不同的需求,可以将插入操作分为以下几种: - **头部插入**:在链表的头部...

    判断链表是否相交的几种算法1

    本篇文章讨论了四种判断两个单链表是否相交的算法,这些算法主要应用于解决《编程之美》中的相关问题。 **解法一**是最直观的方法,称为“两两遍历法”。它通过分别遍历两个链表h1和h2,寻找h1中的节点是否出现在h2...

    C++经典算法 双向链表

    常用的排序方法之一是在链表中插入节点时保持已插入节点的有序性,从而实现整个链表的排序。 #### 交换两个节点 给定代码中的`linkySwap(linky head, linky one, linkytwo)`函数用于交换链表中任意两个节点的位置...

    88.cpp,设计算法判断单循环链表是否每个结点的值都是偶数

    设计算法判断单循环链表是否每个结点的值都是偶数,建立链表,判断,显示。 对任意输入的一组数据,建立一个递增有序的单链表。 将单链表L中的奇数项和偶数项结点分解开,并分别连成一个单链表。 用递增有序的链表A...

    顺序表 链表 双链表的增删查改操作及链表逆置等常用线性表算法.zip

    在本压缩包中,我们重点关注了三种类型的线性表:顺序表、链表和双链表,以及它们的增删查改操作和链表逆置等常见算法。 顺序表是一种最简单的线性表实现,它在内存中是连续存储的,可以通过数组来表示。对于顺序表...

    数据结构-链表逆置算法实现

    在本话题中,我们将深入探讨“数据结构-链表逆置算法实现”。链表逆置是指将链表中的元素顺序反转,即原本的第一个元素变为最后一个,最后一个元素变为第一个,以此类推。这个过程对于理解和掌握链表操作非常有帮助...

    线性链表查询算法

    查询算法是线性链表中最常用的操作之一。对于循环链表来说,查询操作同样遵循从头节点开始,逐个比较节点数据的过程,直到找到目标值或完成整个链表的遍历。循环链表的查询算法可以采用以下步骤: 1. **初始化指针*...

    实用算法实验_双向链表

    逐字符读取键盘输入的合法字符串,并依次插入到双向链表中。具体的,对于当前读取的字符, 构造其对应的结点。 利用头插法(或尾插法)将该结点按照键盘输入的顺序插入到双向链表中。 3、判断双向链表中各节点...

    链表算法集锦

    这是一个关于链表算法的类,里面收集的算法还是比较全面的,当然,由于本人水平有限,可能在算法中存在一些错误,欢迎大家指正

    有序链表合并算法动态演示系统的毕业设计文档及系统 JAVA

    有序链表合并算法是计算机科学中的一个重要概念,特别是在数据结构和算法分析中。这个算法的主要目的是将两个或多个已排序的链表合并成一个单一的、有序的链表。在本毕业设计中,该算法被动态地演示,使得学生能够更...

    <<算法与数据结构>>链表程序例

    ### 知识点详解:《算法与数据结构》之链表程序示例 #### 链表基础概念 链表是一种动态数据结构,由一系列节点组成,每个节点包含数据元素和指向下一个节点的指针。链表在内存中是不连续的,通过指针将这些节点...

    数据结构 链表的相关算法的用C++语言实现

    ### 数据结构:链表的相关算法的C++语言实现 #### 概述 本文将详细介绍一个基于C++语言实现的单向链表数据结构及其相关的算法。该程序主要实现了链表的基本操作,包括创建、删除、插入节点以及遍历打印整个链表的...

Global site tag (gtag.js) - Google Analytics