题目介绍

来源:腾讯笔试                         难度系数:★★★☆☆                  考察频率:★★★★☆

题目描述:

给定一个带头结点的单链表,请将其逆序。即如果单链表原来为 head->1->2->3->4-> 5->6 ->7,那么逆序后变为head->7->6->5->4->3->2->1。

分析解答

分析

由于单链表与数组不同,单链表中每个结点的地址都存储在其前驱结点的指针域中,因此,对单链表中任何一个结点的访问只能从链表的头指针开始进行遍历。在对链表的操作过程中,需要特别注意在修改结点指针域的时候,记录下后继结点的地址,否则会丢失后继结点。

解答

方法一:就地逆序

方法一思路

在遍历链表的时候,修改当前结点的指针域的指向,让其指向它的前驱结点。为此需要用一个指针变量来保存前驱结点的地址。此外,为了在调整当前结点指针域的指向后还能找到后继结点,还需要另外一个指针变量来保存后继结点的地址,在所有的结点都被保存好以后就可以直接完成指针的逆序了。除此之外,还需要特别注意对链表首尾结点的特殊处理。具体实现方式如下图所示。

在上图中,假设当前已经遍历到 cur 结点,由于它所有的前驱结点都已经完成了逆序操作,因此,只需要使 cur.next=pre 即可完成逆序操作,在此之前,为了能够记录当前结点的后继结点的地址,需要用一个额外的指针 next 来保存后继结点的信息,通过上图(1)~(4)四步把实线的指针调整为虚线的指针就可以完成当前结点的逆序。当前结点完成逆序后,通过向后移动指针来对后续的结点用同样的方法进行逆序操作。

方法一示例解答

class LNode:      def  __init__(self):          self.next=None        self.data=None        # 方法功能:对单链表进行逆序 输入参数:head:链表头结点 def  Reverse(head):     # 判断链表是否为空    if  head == None or head.next == None or head.next.next == None:        return    pre = None  #前驱结点    cur = None  # 当前结点    next = None # 后继结点  #把链表首结点变为尾结点    cur = head.next    next = cur.next    cur.next = None    pre = cur    cur = next  #使当前遍历到的结点cur指向其前驱结点    while  cur.next != None:        next = cur.next        cur.next = pre        pre = cur        cur = cur.next        cur = next    #链表最后一个结点指向倒数第二个结点    cur.next = pre  #链表的头结点指向原来链表的尾结点    head.next = cur  if  __name__=="__main__":    i = 1  #链表头结点    head =LNode()    cur = head  #构造单链表    while  i<8:        tmp = LNode()        tmp.data=i        cur.next = tmp        cur = tmp        i +=1    print('逆序前:',end='')    cur = head.next    while  cur != None:        print(cur.data,'',end='')        cur = cur.next    print ('\n逆序后:',end='')    Reverse(head)    cur = head.next    while  cur != None:         print (cur.data,'',end='')         cur = cur.next

程序的运行结果为:

逆序前:1 2 3 4 5 6 7逆序后:7 6 5 4 3 2 1

方法一性能分析

以上这种方法只需要对链表进行一次遍历,因此,时间复杂度为 O(N),其中,N 为链表的长度。但是需要常数个额外的变量来保存当前结点的前驱结点与后继结点,因此,空间复杂度为 O(1)。

方法二:递归法

方法二思路

假定原链表为 1->2->3->4->5->6->7,递归法的主要思路为:先逆序除第一个结点以外的子链表(将 1->2->3->4->5->6->7变为 1->7->6->5->4->3->2),接着把结点 1 添加到逆序的子链表的后面(1->7->6->5->4->3->2 变为 7->6->5->4->3->2->1)。同理,在逆序链表 2->3->4->5->6->7 时,也是先逆序子链表 3->4->5->6->7(逆序为 2->7->6->5->4->3),接着实现链表的整体逆序(2->7->6->5->4->3)转换为(7>6>5>4->3->2)。

方法二示例解答

"""方法功能:对不带头结点的单链表进行逆序输入参数:firstRef:链表头结点"""def  RecursiveReverse(head):      # 如果链表为空或者链表中只有一个元素     if  head is None or head.next is None :          return  head    else :          # 反转后面的结点        newhead=RecursiveReverse(head.next)               # 把当前遍历的结点加到后面结点逆序后链表的尾部        head.next.next=head          head.next=None      return  newhead  """方法功能:对带头结点的单链表进行逆序输入参数:head:链表头结点"""def  Reverse(head):        if   head is None:          return    # 获取链表第一个结点    firstNode=head.next    # 对链表进行逆序    newhead=RecursiveReverse(firstNode)     # 头结点指向逆序后链表的第一个结点    head.next=newhead      return   newhead  

方法二性能分析

由于递归法也只需要对链表进行一次遍历,因此,算法的时间复杂度也为 O(N),其中,N 为链表的长度。递归法的主要优点是:思路比较直观,容易理解,而且也不需要保存前驱结点的地址。缺点是:算法实现的难度较大,此外,由于递归法需要不断地调用自己,需要额外的压栈与弹栈操作,因此,与方法一相比性能会有所下降。

方法三:插入法

方法三思路

从链表的第二个结点开始,把遍历到的结点插入到头结点的后面,直到遍历结束。假定原链表为 head->1->2->3->4->5->6->7,在遍历到 2 的时候,将其插入到头结点后,链表变为head->2->1->3->4->5->6->7,同理将后续遍历到的所有结点都插入到头结点 head 后,就可以实现链表的逆序。

递归输出的主要思路为:先输出除当前结点外的后继子链表,然后输出当前结点,假如链表为:1->2->3->4->5->6->7,那么先输出 2->3->4->5->6->7,再输出 1。同理,对于链表 2->3->4->5->6->7,也是先输出 3->4->5->6->7,接着输出 2,直到遍历到链表的最后一个结点 7 的时候会输出结点 7,然后递归地输出 6,5,…,1。

方法三示例解答

#插入法def  Reverse(head):    # 判断链表是否为空       if  head is None or head.next is None:           return       cur = None #当前结点       next = None #后继结点       cur = head.next.next    # 设置链表第一个结点为尾结点       head.next.next = None     # 把遍历到结点插入到头结点的后面       while  cur is not  None:           next = cur.next           cur.next = head.next           head.next = cur           cur = next#递归def  ReversePrint(firstNode):     if  firstNode is None:            return     ReversePrint  (firstNode.next)     print (firstNode.data,'',end='')

方法三性能分析

以上这种方法也只需要对单链表进行一次遍历,因此,时间复杂度为 O(N),其中,N 为链表的长度。与方法一相比,这种方法不需要保存前驱结点的地址,与方法二相比,这种方法不需要递归地调用,效率更高。

感谢您的阅读,有任何问题欢迎评论区留言。

· END ·

本公众号拥有优而全的高效复习资料,旨在为您的面试求职保驾护航,提高您的职场竞争力,感谢您的支持!

单链表实现一元多项式相加_python面试系列 01如何实现单链表的逆序相关推荐

  1. 数据结构——有序链表的合并,链表实现一元多项式相加

    1.有序链表的合并 void Connect(LinkList a, LinkList b, LinkList& c) {LNode* pa, * pb, * pc;//三个结点指针pa = ...

  2. c语言单链表实现一元多项式相加算法

    给定两个一元多项式,实现两个一元多项式的相加算法.提示:用一条单链表表示一个一元多项式,每个节点包含三个域:指数域.系数域和后继结点链. 可直接运行 #include <stdio.h> ...

  3. 单链表实现一元多项式相加

    严蔚敏2.4部分实现 //Polynomal_Head.h#define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INF ...

  4. 严蔚敏数据结构:链表实现一元多项式相加

    一.基本概念 1.多项式pn(x)可表示成:  pn(x)=a0+a1x+a2x2+-+anxn. listP={(a0,e0),(a1,e1),(a2,e2),-,(an,en) }.在这种线性表描 ...

  5. 架构设计面试系列-01

    1. 软件架构设计都有哪些基本原则? 1.开闭原则(OCP Open Close Principle) Software entities should be open for extension, ...

  6. 网络编程面试系列-01

    1. 应用层中常见的协议都有哪些? 应用层协议(application layer protocol)定义了运行在不同端系统上的应用程序进程如何相互传递报文. 应用层协议 1)DNS:一种用以将域名转 ...

  7. c语言一元多项式相加

    用单链表实现一元多项式相加 #include<stdio.h> #include<stdlib.h> typedef struct Node{float coef;//系数 i ...

  8. C语言实现一元多项式相加

    C语言 链表实现一元多项式相加 这里的代码复制后,可以直接运行,按照规定的输入即可得出多项式的结果. 问题描述 设计一种单链表存储结构,每个节点成员有一个系数和一个指数,以及下一个节点的指针,数据类型 ...

  9. c语言将一个已知头结点的单链表逆序_C语言实现常用数据结构:静态链表数组实现(第5篇)...

    「今天是学习C语言第 148 天」 纸上学来终觉浅,绝知此事要躬行.-- 陆游「冬夜读书示子聿」 # 静态链表 使用数组实现,利用数组下标代替指针,从而实现数据结点之间的先后关系.实现要点: 1.数组 ...

最新文章

  1. 关于libStagefright系列漏洞分析
  2. JAVA SE学习day_04:RandomAccessFile
  3. Spring接入RabbitMQ
  4. leetcode(3)---寻找最大字符串
  5. undefined reference to `pthread_create‘(linux下Clion使用thread报错)
  6. 啊哈算法系列(C语言、python、Java )
  7. loadrunner 商城项目随机选书
  8. vmware上的ubuntu与window共享folder(shared folder disabled.)
  9. LeetCode 404 左叶子之和
  10. 十二、添加RD 授权角色
  11. 时间序列预测算法----Prophet
  12. 16QAM的理论误码率仿真
  13. 1-7华为HCNA认证eNSP基础B
  14. 系统功能性/非功能性需求
  15. PPT处理控件Aspose.Slides功能演示:使用 C# 在 PowerPoint 演示文稿中创建 SmartArt
  16. rpm包的签名问题笔记
  17. 使用 electron-builder 及 electron-updater 给项目配置自动更新
  18. DONNET俱乐部的新拐点-加入“国际.NET协会”The International .NET Association (INETA)
  19. 服务器没有响应客户端,socket编程某些服务器对某些客户端没有响应的问题!!...
  20. 学习笔记1:orangepi的配网及IP登录

热门文章

  1. webrtc 渲染_webRTC 中 timing 信息的使用
  2. JAVA获取程序/jar包所在路径
  3. w10恢复出厂设置_路由器如何恢复出厂设置
  4. 关于一些电脑使用的小技巧
  5. WPF ListView展示层叠信息
  6. Android面试,View绘制流程以及invalidate()等相关方法分析
  7. Codeforces 558(C、D、E)总结
  8. HBase1.2.3 数据模型
  9. Oracle11gR2 RAC+DataGuard安装实施维护2+1_数据库集群容灾视频教程
  10. JSLint JavaScript代码质量审查工具汉化中文版隆重发布