数据结构——链表

写在前面

做算法题时最最重要的是清晰的思路,理清思路然后用代码实现。

链表

链表可以分为单项链表、双向链表、以及环形链表。它在内存中的存储格式如下:

由图可得:

  1. 链表是以节点存储数据,是链式存储
  2. 每个节点包含data和next,data存放数据,next指向下一个节点。
  3. 链表的各个节点不一定是连续存储
  4. 链表可以分为带头节点的链表和不带头节点的链表。
一、单向链表

单项链表最核心的思想是单向,可以理解为只能向一个方向(从头到尾)添加、遍历、读取数据。如图:
单向链表

二、双向链表

双向链表
几点说明:

  1. 单向链表查找的方向只能是一个方向,而双向链表可以向前或向后双向查找。
  2. 单向链表不能自我删除(无法使删除节点后的链表连接起来),需要靠辅助节点。而双向链表,则可以自我删除。所以删除单链表的节点时,总是找到temp,temp是待删除节点的前一个节点。

注意:
调用在链表中间添加、删除节点的方法时,当遍历到双向链表的最后一个节点,要注意pre指针和next指针的指向问题,否则会出现空指针异常。
例:
删除节点temp时,以下代码

temp.pre.next = temp.next;	//构建向后的指针
temp.next.pre = temp.pre;	//构建向前的指针

作用最后一个节点时,temp.next是一个null,null.pre就会出现空指针异常。

三、环形链表

这里用一个问题(约瑟夫环)引出环形链表。

Josephu问题:设编号为1,2,…n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

用单向环形链表清楚直观的解决Josephu问题。

总思路:
先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。
单向环形链表
构建单向环形链表思路:

  1. 先创建第一个节点, 让 first 指向该节点,并形成环形(:first指针不能动,因为后面加入的节点要指向first,形成环形)
  2. 每当创建一个新的节点(boy节点),就把该节点,加入到已有的环形链表中即可。
  3. curBoy指针必须指向的是新加入的boy节点的前一个节点,因为是单向链表,只能单向添加节点(单向链表的特性)。
  4. curBoy.next = boy;
  5. boy.next = first;
    构建单向环形链表

遍历环形链表:

  1. 先让一个辅助指针(变量) curBoy,指向first节点。
  2. 然后通过一个while循环遍历环形链表即可,当curBoy.next == first 结束。

出圈思路:
3. 先创建一个辅助指针(变量) helper , 先指向环形链表的最后这个节点.
补充: 小孩报数前,先让 first 和 helper 移动 k - 1 次
4. 当小孩报数时,让first 和 helper 指针同时 的移动 m - 1 次
5. 这时就可以将first 指向boy的节点出圈。

出圈步骤:

  1. first = first .next (first指针后移)
  2. helper.next = first

原来first 指向的节点就没有任何引用,就会被回收
Talk is cheap. Show me the code.

package DataStructure.linkedlist
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值