在学习数据结构时,相信不少笔友们会被指针这个知识点困住,小小的一个设计到指针的算法可能会耗费你很多时间才可能完善,归咎到底就是没有注意到空指针的发生。本人在下面举个栗子:
已知一个带头节点的单链表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 }
怎么样,问题虽小,但是需要注意啊!平时编程一定要注意这些边界值问题,尤其是涉及到指针的算法。