约瑟夫问题
约瑟夫问题 可问题简单描述为
设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数 到 m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由 此产生一个出队编号的序列
链表
以上问题可以通过单向循环链表来解决,在解决问题之间,先了解下链表数据结构
特点
- 链表是以节点的方式来存储,是链式存储
- 每个节点包含 data 域, next 域:指向下一个节点.
- 如图:发现链表的各个节点不一定是连续存储.
- 链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定
分类
链表有可以分为 单向链表和双向链表。单向链表又分为普通链表和循环链表。具体结构如下图
单向链表
- 有一个head节点,该节点不存储实际数据(也可以存数据,具体自己实现即可)
- 每隔节点为Node,其下有data引用,用来存储数据
- 每一个Node均有一个next引用指向下一个Node,最末Node的next为空
单向循环链表
- 和单向链表类似,其中start、end节点存储实际数据
- end节点next引用指向start
双向链表
- 有start节点和end节点
- 每隔节点均有pre引用指向前一个节点、end引用指向下一个节点
- start节点的pre为空,end节点的next为空
优缺点
链表相对于数组而言
- 链表能够快速实现插入、删除:链表只需要改变next、pre引用指向即可;而数组如果删除中间某个数据,需要将删除位置以后的数据均向前移一位
- 链表申明的时候不需要指定大小,而数组在初始化的时候需要指定大小,数组如果需要扩容则需要将其内数据拷贝
- 链表遍历需要通过next从前向后进行遍历(双向链表可以从后向前),而数组可以直接通过下标直接访问
java中ArrayList利用数组实现,LinkedList利用链表实现
代码请参考
单向链表 SingleLinkedList 测试
单向循环链表 CircleSingleLinkedList 测试 约瑟夫解法请参考 getJosepfuList方法
双向循环链表 DoubleLinkedList 测试