初学数据结构-单链表初探的一些兴奋点

来源:互联网 发布:网贷大数据免费查询 编辑:程序博客网 时间:2024/06/06 09:09
     最近接触单链表的算法,有那么几个亮点,让我很兴奋。
     先回顾一下单链表的定义,是线性表的链接存储表示。只能顺序存取,意味着想找到或者使用 某个结点,都得从首元结点(表头指针)按链接方向遍历过去。

     单链表的结构,是一个递归的定义。链表的指针通过链表结点定义,链表结点又是由链表指针定义的。因此可以把处理n个结点链表的问题,转化为处理n-1个结点的问题,缩小范围。就这样,从顶之下,到链表尾部的时候,为终止条件,返回想要的值,一步步递归回来。

     上边说到,顺序存取时从首元结点开始遍历。但是每一次往后遍历,指针相应后移,对着单链表来说是相对静止的,但是在内存里感觉虚无缥缈,很容易丢失指针引用,找不到它。这时候,使用头结点L,来引导一群排成队的结点小弟。想用单链表的时候,找头结点就可以了。头结点的数据域为空,指针域指向首元结点。
     从我看到的一些单链表的算法,有无头结点,作为形参的时候是有区别的。
     使用头结点的时候,形参一般是(LinkList &L);不使用头结点的时候,形参是链表首元结点的引用(LinkNode *&h),*&是普通变量的引用,可以改变实参。


     看到很多这样的问题,一条单链表,表头指针为h,遍历的时候,把指针的顺序逆转(指向前一个结点)
     大概的意思就是 a1->a2->a3->a4这么个链表,要变成a1<-a2<-a3<-a4
     题目只说有表头指针,表头指针是指着首元结点的,到底用不用头结点呢。以下分类讨论:
有头结点的逆转:
     有头结点的,相对来说简单一点,因为有头结点这么个参照物,可以大刀阔斧的动手。
     思路:
     把变换后的链表这么看 a4->a3->a2->a1
     用一个指针指着首元结点,这时候把头结点拿出来,作为一个新的结果链,可以看到结果链与原链表相反。即先把a1从原链表取出来,接在结果链上;再把a2取出来,放在结果链第一位,a1就被挤到后边了。
      写成代码,就完成了。有一些细节可以关注,用一个指针p,始终对着原链表。把原链表首元结点摘下时,需要改变首元结点的指针域。如果这时候p也跟着跑到结果链,原链表就丢了。所以需要先把p先放到原链表首元结点的下一项,避难,下次遍历的时候用,即p-p->link。然后用再用一个临时指针pr,指着首元结点,用pr对首元结点进行操作。
     总结一下,用带头结点的单链表进行逆转的时候,用到p和pr两个指针。
不带头结点的逆转:
     不带头结点的话,当前指针h指针域逆转的时候,需要有一个指在前一项的指针。可以想到,它的前一项已经完成逆转了。但是,两个指针改变的时候,需要第三个指针做temp,缓冲一下,我们把这个指针放在当前指针h的右边,即把h指针夹在中间。因此我们常用三个指针来完成无头结点链表的逆转。
     思路:
     开始时,中间结点h指向首元结点,左边的指针pr=NULL,右边的指针p=h->link。开始遍历了,中间结点指针域逆转,然后三个结点向右平移一个结点的位置,继续逆转下一个元素。
 
     对头结点的使用,经常把原链表用个指针固定一下,然后把头结点摘下来,一个链表就变成了两个,用起来非常爽。
      结束!
新手上路,希望大神多多指正
0 0
原创粉丝点击