由一道算法题总结单向链表经验——PTA1015总结

在解答PTA1015的时候,花费了较多的时间尝试了一下单向链表的创建和排序,结果是令人失望的,因为自身经验的不足,导致前期错误出现的非常多,这时候就体现出链表不方便的地方了——调试不友好。在花费一晚时间调试错误之后,又出现了众多奇怪的问题,诸如超时、答案错误等等,仔细观察了一下,对于小量数据,好像是没有错误,但是一旦面临大规模数据,就力不从心了,特此总结。

下面我们从几个问题入手,对产生的问题简单地进行剖析,希望自己能长个教训,避免日后工作和研究过程中出现此类问题,也顺便复习下大学内学到的关于链表的知识。 

  1. 链表的数据结构及C语言实现
  2. 使用链表的好处与坏处
  3. 如何调试链表
  4. 使用链表的性能问题 

1、在C语言中,链表的表示可以借助结构体(Struct)来表示节点,一个典型的节点数据结构如下:

struct ListNode{
    int a;
    int b;
    struct ListNode* Next;
}Node;

其中除了包含必要的数据项外,还包含一个指向下一节点的指针。通过各节点串联,可以形成一个简单的链表。

几种典型常用的链表

需要注意的是,链表作为一种线性表,但不支持随即访问,即按下标访问。访问尾部的元素需要遍历该元素之前的所有元素,在某些方面将会显著降低效率。这也是接下来要讲的。 

2、链表的好处与坏处

使用链表可以满足某些动态的扩展和删减,譬如在Node1与Node2之间插入一个元素,只需要更改Node1的指针即可,而如果使用数组,那么还需要做一个连续后移操作,复杂度也就上去了。当然,坏处也是显而易见,除了以上说的不支持随即访问外,还存在着运行状况难以监管的情况,尤其是对新手不友好,指针的大量使用容易造成一些未知错误,且不容易调试。

3、关于调试链表的一点经验

  1. 调试链表最好能够在遍历链表时做一个打印工作,连同节点地址一同打印,这样可以尽早发现一些越界操作。指针越界是一个大坑,遍历打印调试是一个好方法。由于链表动态增长特性,调试越界错误与数据规模无关,也就是可以通过少量数据发现这种错误,除非内存堆栈被填满。
  2. 调试链表时也可以配合数组进行,通过创建一个辅助数组,记录链表处理过程的结果,这样就可以不需要打印,在调试中直接通过窗口监测,会使输出界面比较干净。
  3. 链表在处理插入操作时容易产生断链、循环、跳跃等错误,即链表前后断开、链表出现不该出现的环路、链表几个节点脱离链表。对于这些错误也是建议通过遍历链表,尽早发现,否则会影响之后的所有操作。

4、关于性能问题

以下是本人在处理PTA1015过程中使用的两种算法比较:

 

单向链表BubbleSort 性能分析 10w条数据
数组qsort函数 性能分析 10w数据

 当然以上只是本人测试结果,没有普遍意义,但是对于大家来说也说明了一点,某些意义上自己造轮子不一定有官方库好用。四五倍的运行时间差距说明了一切。作者的BubbleSort操作为交换两个节点的指针,其中至少有6条语句,交换前指针和后指针。如果是交换数据,则至少有9条语句,因为有三个变量。我想运行时间如此之长也跟这些操作有关。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值