关于链表算法需要注意的空指针异常

在学习数据结构时,相信不少笔友们会被指针这个知识点困住,小小的一个设计到指针的算法可能会耗费你很多时间才可能完善,归咎到底就是没有注意到空指针的发生。本人在下面举个栗子:

已知一个带头节点的单链表L,其节点如下定义:

1 template <typename T>
2 struct LinkList{
3 T data;
4 LinkList<T> * head;
5 }

现在设计一个算法,查找最后一个值为e的节点的逻辑结构:
呵呵,看着挺简单的吧,只需要遍历一遍链表即可查找到结果,下面附上我的原始代码:

 1 template <typename T>
 2 int FindLast(LinkListClass<T> L,T e)
 3 {
 4     LinkList<T> * p=L.head;
 5     int position=0,i=0;
 6     while(p!=NULL)  ①
 7     {
 8         p=p->next;  ②
 9         i++;
10         if (p->data==e)   ③
11             position=i;
12     }
13
14     return position; //如果查找成功返回其逻辑序号,否则返回0
15 }

然后我编译,链接一下,都没有报错,可是在运行过程中就会出错无法继续运行,这就是运行时错误

看看,根本不知道是何错,于是我调试了一下,发现问题的根本在于上面源码的一二三标记处的次序。

这个函数忽略了空指针异常报错,如果当指针p指向链表L的尾节点时,此时进入while循环,经过语句②,p==NULL了,然后执行③就会包空指针异常

问题找到了,解决起来就会容易得多,下面我举出一种解决代码(其实还有很多)

 1 template<typename T>
 2 int FindLast(LinkListClass<T>& L, T e)
 3 {
 4     int position = 0;
 5     int i = 1;
 6     LinkList<T> * p = L.head->next;
 7     while (p != NULL)
 8     {
 9         if (p->data == e)
10             position = i;
11         i++;
12         p = p->next;
13     }
14     return position;
15 }

怎么样,问题虽小,但是需要注意啊!平时编程一定要注意这些边界值问题,尤其是涉及到指针的算法。

原文地址:https://www.cnblogs.com/gaochaochao/p/8407321.html

时间: 2024-10-23 21:00:31

关于链表算法需要注意的空指针异常的相关文章

链表算法-链表前面插入节点

链表算法-链表前面插入节点

链表算法-后面插入节点

链表算法-后面插入节点

链表算法递归的理解

一:前言 今天在博客园里面看了一篇文章http://www.cnblogs.com/huangxincheng/p/4051854.html(单链表的倒置),其实自己看了一个小时最后那点还是没看明白,自己的不明白在于,递归调用到最后执行递归下面的代码是怎么执行的,如果执行了,执行时的数据从哪来的?我就是这点想不明白,但是我自己能看懂这个代码.此时的想不明白不知道算不算钻牛角尖.还是先说说自己的理解吧!!! 二:我把他的那段代码复制过来了,单链表我自己又随便写个是:9---->6------->

iOS 单链表算法的一些问题

链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域. 相比于线性表顺序结构,操作复杂.由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn

反转链表算法Java实现

之前遇到反转链表的算法,比较晦涩难解,但其实挺简单的. 目标:将一个顺序链表反转. 思路:用三个辅助节点,每次实现一个节点的指向反转,即他的后继变为他的前驱. 三个辅助节点: p  q  r  按顺序分别指向 节点0,1,2, 然后一次次移动,指向1,2,3 : 2,3,4...... 算法分为三部分: 第一部分:初始化部分: q是中心节点,是每次反转的节点,于是q是由函数参数传入的,前面的节点p一个是null,后面的节点r是q的后继节点q.next 第二部分:循环部分 分为两个操作: 1.反转

链表算法总结

这篇博客就总结一下关于链表的各种题,来源POJ和LeetCode,一点一点的扩充,遇到题目就补进来. (1)LeetCode  61. Rotate List 双指针,先计数求长度,不要一前一后一起跑 public class Solution { public ListNode rotateRight(ListNode head, int n) { if (head==null||head.next==null) return head; ListNode dummy=new ListNode

zList一个块状链表算法可以申请和释放同种对象指针,对于大数据量比直接new少需要差不多一半内存

zList是一个C++的块状内存链表,特点: 1.对于某种类别需要申请大量指针,zList是一个很好的帮手,它能比new少很多内存. 2.它对内存进行整体管理,可以将数据和文件快速互操作 3.和vector对象存储对比,vector存储的对象不能使用其指针,因为vector内容变化时vector存储对象的指针会变化 4.zList也可以当做顺序的数组使用,它有自己的迭代器,可以遍历整个数组 下面是申请5千万个RECT指针对比结果: zList申请五千万RECT指针内存占用: 直接new五千万RE

反转链表算法题

反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶:你可以迭代或递归地反转链表.你能否用两种方法解决这道题? 解决方案 方法一:迭代 假设存在链表 1 → 2 → 3 → Ø,我们想要把它改成 Ø ← 1 ← 2 ← 3. 在遍历列表时,将当前节点的 next 指针改为指向前一个元素.由于节点没有引用其上一个节点,因此必须事先存储其前一个元素.在更改引用之前,还需要另一个

链表算法题

单链表 function LinkedList() { //需要插入链表的元素 var Node = function(element) { this.element = element;//元素的值 this.next = null;//指向下一个节点项的指针 }; var length = 0;//链表的长度 var head = null;//链表中第一个节点(的引用) //向链表尾部追加元素 this.append = function(element) { var node = new