大厂面试经典单链表例题(创建有序单链表,逆置单链表,判断链表是否有环,取链表中间节点)(含核心代码与解析)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 大厂面试经典单链表例题(创建有序单链表,逆置单链表,判断链表是否有环,取链表中间节点)(含核心代码与解析)

目录


引言

创建有序单链表

题目

算法思路

代码实现

逆置单链表

题目

算法思路

代码实现

判断单链表是否有环

题目

算法思路

代码实现

取单链表中间节点的数值

题目

算法思路

代码实现

总结


引言


有关单链表的基础操作,如动态分布空间,单链表创建的思路,单链表的增、删、改、毁,笔者已经在博客中详细解析了,有兴趣的小伙伴也可以取看看,

本次介绍的是有关单链表的四道大厂面试典中典,其中的逆置单链表更是重量级,大家放心食用😁


正文


创建有序单链表


题目


创建一个升序或降序的单链表,并打印输出,例如:

输入: 1 5 6 2 3
输出: 1 2 3 5 6


算法思路


算法思路:

       s1:每获得一个数据 就创建一个数据结点

       s2:把数据写入到数据结点中去

       s3:把写好的数据结点加入到链表中去

           分情况讨论:

               从无到有

               从少到多

                   头插法

                   尾插法

                   中间插入

我们将算法思路待人代码中观察


代码实现


Node *create_sort_list()
{
  u4 d;
  Node *pnew = NULL;    //指向 新创建的节点
  Node *head = NULL;
  while(1)
  {
    scanf("%d",&d);
    if(d == 0)        //约定输入0,结束输入
      break;
    pnew = malloc(sizeof(*pnew));    //分配空间
    pnew->data = d;                  //将数据写入数据节点
    pnew->next = NULL;
        //将写好的数据节点加入到链表
    if(head == NULL)                 //从无到有
    {
      head = pnew;
    }
    else                             //从少到多
    {
      Node *p = head;
      Node *pre = NULL;
      while(p)                     //找出链表中比新节点大的数据打的节点
      {
        if(p->data > pnew->data)    //找到就返回这个节点
        {
          break;
        }
        else                        //没找到就往下遍历,直到p==NULL,即新节点的值是最大的,插到末尾
        {
          pre = p;
          p = p->next;
        }
      }
      if(p != NULL)
      {
        if(p == head)            //头插法
        {
          pnew->next = head;   //新节点指向链表的第一个,即指向head
              head = pnew;     //然后将head指向新节点
        }
        else                     //插入中间
        {
          pnew->next = p;
          pre->next = pnew;
        }
      }
      else                         //插到末尾
      {
        pre->next = pnew;
      }
    }
  }
  return head;
}


逆置单链表


题目


就地逆置一个链表(不允许申请新的结点空间)

   例子:

       h: 1 5 3 4

       =>

       h: 4 3 5 1

       要求:

           不允许申请新的结点空间


算法思路


把原链表的每一个结点 ,摘下来 ,然后按头插法 加入到新链表。

 

Node *reverse(Node *h)
{
  //创建一个指向逆置后链表的第一个结点
  //创建一个指针p为遍历指针
  while(p)
  {
      //step 1:把h指向的链表的第一个结点摘下来
    //step2: 按照头插法 把p结点 加入到逆置后的链表first
    //step2.1 从无到有
    //step2.2 从少到多
  }
      //返回逆置链表的第一个节点
}


代码实现


Node *reverrse(Node *h)
{
  Node *first = NULL;        //创建一个指向逆置后链表的第一个结点
  Node *p = h;               //创建一个指针p为遍历指针
  while(p)
  {
        //step 1:把h指向的链表的第一个结点摘下来
    h = h->next;
    p->next = NULL;
        //step2: 按照头插法 把p结点 加入到逆置后的链表first
    //step2.1 从无到有
    if(first == NULL)
    {
      first = p;
    }
    else            //step2.2 从少到多
    {
      p->next = first;
      first = p;
    }
    p = h;
  }
  return first;        //返回逆置链表的第一个节点
}


判断单链表是否有环


题目


判断一个单链表是否有环


算法思路


快慢指针

定义两个指针p和q;

让p每次走两步,q每次走一步

当p和q相遇时则说明有环,否则就没有环。


代码实现


/*
is_a_ring:判断单链表是否有环
    @h:指定的单链表的第一个节点指针
    返回值:
        1 有环
        0 无环
 */
int is_a_ring(Node *h)
{
  Node *p = NULL;//fast指针
  Node *q = NULL;//slow指针
  p = h;
  q = h;
  while(p)
  {
    p = p->next;
    if(p == NULL)
    {
        break;
    }
    p = p->next;
    q = q->next;
    if(p == q)
    {
      return 1;
    } 
  }
  return 0;
}


取单链表中间节点的数值


题目


写一个程序,获取链表中间结点的值

       例子:

           对于奇数结点 返回中间结点值

           输入 :1 2 3 4 5

           输出:3

           对于偶数结点  返回较小下标的值

           输入: 25 69 78 45 96 -21 -47 62

           输出:45


算法思路


定义两个指针p和q;

让p每次走两步 q走一步

当p走到链表末尾时 此时q刚好走到链表的中间结点。


代码实现


void get_middle_v(Node *h)
{
  Node *pk = h;    //快指针
  Node *pm = h;    //慢指针
  while(1)
  {
    if(pk->next == NULL)    //快指针已经到了最后一个(奇数个)
    {
      printf("%d\n",pm->data);
      break;
    }
    else
    {
      pk = pk->next->next;        //快指针的下一个是最后一个(偶数个)
      if(pk == NULL)
      {
        printf("%d\n",pm->data);
        break;
      }
      pm = pm->next;
    }
  }
}


总结


这些题目其实总体难度不高,更重要的是体会其中的算法思路,分类思想,利用好单链表本身的空间余节点取解决问题。

相关文章
|
16天前
|
敏捷开发 安全 测试技术
软件测试的艺术:从代码到用户体验的全方位解析
本文将深入探讨软件测试的重要性和实施策略,通过分析不同类型的测试方法和工具,展示如何有效地提升软件质量和用户满意度。我们将从单元测试、集成测试到性能测试等多个角度出发,详细解释每种测试方法的实施步骤和最佳实践。此外,文章还将讨论如何通过持续集成和自动化测试来优化测试流程,以及如何建立有效的测试团队来应对快速变化的市场需求。通过实际案例的分析,本文旨在为读者提供一套系统而实用的软件测试策略,帮助读者在软件开发过程中做出更明智的决策。
|
6天前
|
SQL 人工智能 机器人
遇到的代码部份解析
/ 模拟后端返回的数据
11 0
|
7天前
|
设计模式 存储 算法
PHP中的设计模式:策略模式的深入解析与应用在软件开发的浩瀚海洋中,PHP以其独特的魅力和强大的功能吸引了无数开发者。作为一门历史悠久且广泛应用的编程语言,PHP不仅拥有丰富的内置函数和扩展库,还支持面向对象编程(OOP),为开发者提供了灵活而强大的工具集。在PHP的众多特性中,设计模式的应用尤为引人注目,它们如同精雕细琢的宝石,镶嵌在代码的肌理之中,让程序更加优雅、高效且易于维护。今天,我们就来深入探讨PHP中使用频率颇高的一种设计模式——策略模式。
本文旨在深入探讨PHP中的策略模式,从定义到实现,再到应用场景,全面剖析其在PHP编程中的应用价值。策略模式作为一种行为型设计模式,允许在运行时根据不同情况选择不同的算法或行为,极大地提高了代码的灵活性和可维护性。通过实例分析,本文将展示如何在PHP项目中有效利用策略模式来解决实际问题,并提升代码质量。
|
2月前
|
开发者 图形学 Java
揭秘Unity物理引擎核心技术:从刚体动力学到关节连接,全方位教你如何在虚拟世界中重现真实物理现象——含实战代码示例与详细解析
【8月更文挑战第31天】Unity物理引擎对于游戏开发至关重要,它能够模拟真实的物理效果,如刚体运动、碰撞检测及关节连接等。通过Rigidbody和Collider组件,开发者可以轻松实现物体间的互动与碰撞。本文通过具体代码示例介绍了如何使用Unity物理引擎实现物体运动、施加力、使用关节连接以及模拟弹簧效果等功能,帮助开发者提升游戏的真实感与沉浸感。
39 1
|
2月前
|
存储 SQL 安全
【数据库高手的秘密武器:深度解析SQL视图与存储过程的魅力——封装复杂逻辑,实现代码高复用性的终极指南】
【8月更文挑战第31天】本文通过具体代码示例介绍 SQL 视图与存储过程的创建及应用优势。视图作为虚拟表,可简化复杂查询并提升代码可维护性;存储过程则预编译 SQL 语句,支持复杂逻辑与事务处理,增强代码复用性和安全性。通过创建视图 `high_earners` 和存储过程 `get_employee_details` 及 `update_salary` 的实例,展示了二者在实际项目中的强大功能。
29 1
|
2月前
|
Java 开发者 UED
“Java开发者必看:异步编程实战解析,掌握这些技巧,让你的代码跑得更快!
【8月更文挑战第30天】随着互联网技术的发展,系统性能和用户体验成为关注焦点。异步编程作为提高应用响应速度和吞吐量的技术,在Java中广泛采用。本文详细介绍了Java异步编程的概念与优势,并通过实战示例展示了如何利用Future、Callable及CompletableFuture在实际项目中实施异步编程,帮助开发者更好地理解和应用这一技术。
40 2
|
2月前
|
开发者 图形学 API
从零起步,深度揭秘:运用Unity引擎及网络编程技术,一步步搭建属于你的实时多人在线对战游戏平台——详尽指南与实战代码解析,带你轻松掌握网络化游戏开发的核心要领与最佳实践路径
【8月更文挑战第31天】构建实时多人对战平台是技术与创意的结合。本文使用成熟的Unity游戏开发引擎,从零开始指导读者搭建简单的实时对战平台。内容涵盖网络架构设计、Unity网络API应用及客户端与服务器通信。首先,创建新项目并选择适合多人游戏的模板,使用推荐的网络传输层。接着,定义基本玩法,如2D多人射击游戏,创建角色预制件并添加Rigidbody2D组件。然后,引入网络身份组件以同步对象状态。通过示例代码展示玩家控制逻辑,包括移动和发射子弹功能。最后,设置服务器端逻辑,处理客户端连接和断开。本文帮助读者掌握构建Unity多人对战平台的核心知识,为进一步开发打下基础。
66 0
|
2月前
|
开发者 图形学 C#
揭秘游戏沉浸感的秘密武器:深度解析Unity中的音频设计技巧,从背景音乐到动态音效,全面提升你的游戏氛围艺术——附实战代码示例与应用场景指导
【8月更文挑战第31天】音频设计在游戏开发中至关重要,不仅能增强沉浸感,还能传递信息,构建氛围。Unity作为跨平台游戏引擎,提供了丰富的音频处理功能,助力开发者轻松实现复杂音效。本文将探讨如何利用Unity的音频设计提升游戏氛围,并通过具体示例代码展示实现过程。例如,在恐怖游戏中,阴森的背景音乐和突然的脚步声能增加紧张感;在休闲游戏中,轻快的旋律则让玩家感到愉悦。
43 0
|
2月前
|
开发者 图形学 C#
深度解密:Unity游戏开发中的动画艺术——Mecanim状态机如何让游戏角色栩栩如生:从基础设置到高级状态切换的全面指南,助你打造流畅自然的游戏动画体验
【8月更文挑战第31天】Unity动画系统是游戏开发的关键部分,尤其适用于复杂角色动画。本文通过具体案例讲解Mecanim动画状态机的使用方法及原理。我们创建一个游戏角色并设计行走、奔跑和攻击动画,详细介绍动画状态机设置及脚本控制。首先导入动画资源并添加Animator组件,然后创建Animator Controller并设置状态间的转换条件。通过编写C#脚本(如PlayerMovement)控制动画状态切换,实现基于玩家输入的动画过渡。此方法不仅适用于游戏角色,还可用于任何需动态动画响应的对象,增强游戏的真实感与互动性。
58 0
|
2月前
|
图形学 开发者
【Unity光照艺术手册】掌握这些技巧,让你的游戏场景瞬间提升档次:从基础光源到全局光照,打造24小时不间断的视觉盛宴——如何运用代码与烘焙创造逼真光影效果全解析
【8月更文挑战第31天】在Unity中,合理的光照与阴影设置对于打造逼真环境至关重要。本文介绍Unity支持的多种光源类型,如定向光、点光源、聚光灯等,并通过具体示例展示如何使用着色器和脚本控制光照强度,模拟不同时间段的光照变化。此外,还介绍了动态和静态阴影、全局光照及光照探针等高级功能,帮助开发者创造丰富多样的光影效果,提升游戏沉浸感。
39 0

推荐镜像

更多
下一篇
无影云桌面