一、链表介绍
链表内存中的状态以及小结


二、单链表的应用实例
完整代码:
SingleLinkedListDemo.java
创建节点以及管理链表类
说明:需要创建两个类,一个是节点类,另一个是管理链表的类
① 节点类中需要id、name、sickname以及节点类(用于指向下一个节点)
② 管理链表中的类 首先创建一个头节点(里面没有数据,并且保持不变),包含方法有:添加方法(插入到链表尾部),遍历链表。
如下:
//创建管理链表的类class SingleLinkedList{//先初始化一个头节点, 头节点不要动, 不存放具体的数据HeroNode head = new HeroNode(0, "", "");...其他等方法}//创建节点class HeroNode{public int id;public String name;public String nickname;public HeroNode next;//创建一个构造器,存放id、name、nicknamepublic HeroNode(int id, String name, String nickname) {super();this.id = id;this.name = name;this.nickname = nickname;}@Overridepublic String toString() {return "HeroNode [id=" + id + ", name=" + name + ", nickname=" + nickname + "]";}}
第一种添加方式:添加到链表尾部(包含遍历)
说明:下面是添加节点到链表尾部的方法以及遍历链表的方法。
package LinkedList;//创建管理链表的类class SingleLinkedList{//先初始化一个头节点, 头节点不要动, 不存放具体的数据HeroNode head = new HeroNode(0, "", "");//进行添加节点到末尾public void addNode(HeroNode node) {//首先使用一个临时变量代替headHeroNode temp = head;//寻找到链表的最底部while(true) {if(temp.next == null) {break;}temp = temp.next;}//插入node节点到最底部temp.next = node;}//遍历链表public void showList() {//判断链表是否为空if(head.next == null) {System.out.println("链表为空,无法进行遍历数据!");return;}//使用一个临时变量获取到链表下一个节点HeroNode temp = head.next;while(true) {if(temp == null) {break;}System.out.println(temp);temp = temp.next;}}}
进行测试:
package LinkedList;public class SingleLinkedListDemo {public static void main(String[] args) {SingleLinkedList list = new SingleLinkedList();//创建四个节点HeroNode node1 = new HeroNode(1, "丁明", "青龙偃妈刀");HeroNode node2 = new HeroNode(2, "小殷", "优雅男神");HeroNode node3 = new HeroNode(3, "单泽鹏", "马尾小萝莉");HeroNode node4 = new HeroNode(4, "顾天乐", "金刚小铁拳");//进行添加操作list.addNode(node3);list.addNode(node1);list.addNode(node2);//不能进行重复添加相同的节点,可能会发生死循环//list.addNode(node3);list.addNode(node4);//进行遍历链表list.showList();}}
运行结果:
第二种添加方式:根据id属性排序添加

说明:addNodeById()是根据id号链式添加的方法,根据id号从小到大进行添加。
① 首先需要一个辅助节点temp也就是进行插入节点位置的前一个节点。
② 每次插入相当于遍历链表,从中找出与id位置相匹配的位置插入,在进行遍历判断过程中,会有三种情况,
第一种是没有找到插入中间位置,插入到尾部,使用temp.next==null判断。
第二种是插入id与原有链表中的id相同,提示无法插入,使用temp.next.id==node.id。
第三种是找到在链表中插入的位置,使用temp.next.id>node.id来判断
插入过程说明:
插入只有两种情况也就是插入到尾部,另一种是插入到链表中,temp代表的插入位置之前的一个节点,那么首先得先将temp的next值赋给node的next也就是node.next = temp.next,
(注意不能直接将node作为temp的next值,这样的话原先temp的next值就会被覆盖从而丢失)
接着将node值赋给temp的next位置,temp.next = node。
flag为true实际代表着链表无法插入id相同的情况,为false代表可以插入,如插入到尾部或者链表中间。
//创建管理链表的类class SingleLinkedList{...public void addNodeById(HeroNode node) {//temp就代表待插入节点的前一个节点HeroNode temp = head;//这个flag代表是否有相同id值,true表示不能插入,false表示能插入boolean flag = false;while(true) {//当temp节点的下一个节点为null,说明在尾部了,跳出循坏在尾部添加if(temp.next == null) {break;}//当temp节点下一个节点的id与待插入节点的id相同,flag设置为true,表明不能插入if(temp.next.id == node.id) {flag = true;break;}//当temp节点下一个节点的id大于待插入节点id,跳出循环,将node节点插入到temp之后if(temp.next.id > node.id) {break;}//方便进行遍历temp = temp.next;}if(flag) {System.out.println("插入的节点id已存在,无法插入");}else {//首先插入节点的next先获取到temp的next节点node.next = temp.next;//再将node节点插入到temp节点之前temp.next = node;}}
测试过程:
package LinkedList;public class SingleLinkedListDemo {public static void main(String[] args) {SingleLinkedList list = new SingleLinkedList();//创建四个节点HeroNode node1 = new HeroNode(1, "丁明", "青龙偃妈刀");HeroNode node2 = new HeroNode(2, "小殷", "优雅男神");HeroNode node3 = new HeroNode(3, "单泽鹏", "马尾小萝莉");HeroNode node4 = new HeroNode(4, "顾天乐", "金刚小铁拳");//进行添加操作list.addNodeById(node3);list.addNodeById(node2);list.addNodeById(node1);list.addNodeById(node4);list.addNodeById(node1);//进行遍历链表System.out.println("遍历结果:");list.showList();}}
运行结果:
修改节点方法(根据id)

说明:**依旧使用一个辅助节点temp,并且进行遍历修改
① 首先判断是否为空链表,是的话直接退出。
② **在遍历过程中,有两种情况,一种是没有遍历到结尾没有找到修改位置,第二种情况,找到对应id位置进行修改,这里使用flag(true表示能够修改,false表示不能修改)
//创建管理链表的类class SingleLinkedList{...// 修改节点,根据id编号进行修改public void updateNode(HeroNode newnode) {// 创建一个辅助节点,令temp为head的nextHeroNode temp = head.next;// 判断是否为空链表情况if (temp == null) {System.out.println("链表为空,无法进行修改!");return;}// true表示能够修改, false表示不能修改boolean flag = false;while (true) {// 表示到达链表末尾,无法进行插入if (temp == null) {break;}// 找到对应id相同的英雄if (temp.id == newnode.id) {flag = true;// 表示能够进行修改break;}// 进行遍历使用temp = temp.next;}if (flag) {temp.name = newnode.name;temp.nickname = newnode.nickname;System.out.printf("修改id【%d】成功!\n",newnode.id);} else {System.out.println("链表中无法找到对应id英雄,修改失败!");}}}
测试过程:**
package LinkedList;public class SingleLinkedListDemo {public static void main(String[] args) {SingleLinkedList list = new SingleLinkedList();//创建四个节点HeroNode node1 = new HeroNode(1, "丁明", "青龙偃妈刀");HeroNode node2 = new HeroNode(2, "小殷", "优雅男神");HeroNode node3 = new HeroNode(3, "单泽鹏", "马尾小萝莉");HeroNode node4 = new HeroNode(4, "顾天乐", "金刚小铁拳");//进行添加操作list.addNodeById(node3);list.addNodeById(node2);list.addNodeById(node1);list.addNodeById(node4);//进行遍历链表System.out.println("修改前遍历结果:");list.showList();//进行修改操作list.updateNode(new HeroNode(1, "小丁", "青龙偃月刀"));//list.updateNode(new HeroNode(6, "小丁", "青龙偃月刀"));System.out.printf("\n修改后遍历结果:\n");list.showList();}}
运行结果:

删除节点方法

说明:想要删除节点,需要找到删除节点的前一个节点,再进行删除即可。
class SingleLinkedList{...//根据id来删除节点public void delNode(int id) {if(head.next == null) {System.out.println("链表为空,无法删除!");return;}HeroNode temp = head;//true用来表示找到删除的节点,false表示未找到删除的节点boolean flag = false;while(true) {//到链表末尾没有找到对应节点if(temp.next == null) {break;}//找到temp的下一节点为对应删除的节点if(temp.next.id == id) {flag = true;break;}//进行遍历temp = temp.next;}if(flag) {temp.next = temp.next.next;System.out.printf("成功删除id【%d】",id);System.out.println();}else {System.out.printf("链表中未找到对应id【%d】节点,删除失败!",id);System.out.println();}}}
测试运行:
package LinkedList;public class SingleLinkedListDemo {public static void main(String[] args) {SingleLinkedList list = new SingleLinkedList();//创建四个节点HeroNode node1 = new HeroNode(1, "丁明", "青龙偃妈刀");HeroNode node2 = new HeroNode(2, "小殷", "优雅男神");HeroNode node3 = new HeroNode(3, "单泽鹏", "马尾小萝莉");HeroNode node4 = new HeroNode(4, "顾天乐", "金刚小铁拳");//进行添加操作list.addNodeById(node3);list.addNodeById(node2);list.addNodeById(node1);list.addNodeById(node4);//进行遍历链表System.out.println("修改前遍历结果:");list.showList();//进行删除操作list.delNode(5);//删除链表中不存在的情况list.delNode(1);//删除链表中的节点情况list.delNode(2);list.delNode(3);list.delNode(4);list.delNode(2);//空链表时删除情况System.out.printf("\n修改后遍历结果:\n");list.showList();}}
运行结果:
三、单链表的常见面试题
① 求单链表中有效节点的个数

public class SingleLinkedListDemo {//获取链表中的个数public static int getLinedListSize(HeroNode head) {//判断链表为空的情况if(head.next == null) {return 0;}//使用辅助节点int length = 0;HeroNode temp = head.next;while(temp != null) {length++;temp = temp.next;}return length;}}
测试代码:
说明:配合之前单链表的应用来进行测试
public class SingleLinkedListDemo {public static void main(String[] args) {SingleLinkedList list = new SingleLinkedList();//创建四个节点HeroNode node1 = new HeroNode(1, "丁明", "青龙偃妈刀");HeroNode node2 = new HeroNode(2, "小殷", "优雅男神");HeroNode node3 = new HeroNode(3, "单泽鹏", "马尾小萝莉");HeroNode node4 = new HeroNode(4, "顾天乐", "金刚小铁拳");//进行添加操作list.addNodeById(node3);list.addNodeById(node2);list.addNodeById(node1);list.addNodeById(node4);//获取链表中的个数int size = SingleLinkedListDemo.getLinedListSize(list.head);System.out.printf("链表中的节点有%d个。\n",size);}}
运行结果:
② 查找单链表中的倒数第 k 个结点 【新浪面试题】

public class SingleLinkedListDemo {//获取链表的倒数第k个节点public static HeroNode getLastIndexNode(HeroNode head,int k) {//判断链表为空的情况if(head.next == null) {return null;}//获取链表中的个数int size = SingleLinkedListDemo.getLinedListSize(head);//对于k的取值进行判断,若位置不合理返回nullif(k<=0 || k>size) {return null;}//合理情况下求链表中的第size-k个节点//使用一个辅助节点HeroNode temp = head.next;for(int i=1;i<=size-k;i++) {temp = temp.next;}return temp;}}
测试代码:
package LinkedList;public class SingleLinkedListDemo {public static void main(String[] args) {SingleLinkedList list = new SingleLinkedList();//创建四个节点HeroNode node1 = new HeroNode(1, "丁明", "青龙偃妈刀");HeroNode node2 = new HeroNode(2, "小殷", "优雅男神");HeroNode node3 = new HeroNode(3, "单泽鹏", "马尾小萝莉");HeroNode node4 = new HeroNode(4, "顾天乐", "金刚小铁拳");//进行添加操作 这里是按照id进行添加的list.addNodeById(node3);list.addNodeById(node2);list.addNodeById(node1);list.addNodeById(node4);//获取链表中的个数int size = SingleLinkedListDemo.getLinedListSize(list.head);System.out.printf("链表中的节点有%d个。\n",size);//进行遍历链表System.out.println("进行遍历链表:");list.showList();System.out.println();//获取链表的倒数第4个节点HeroNode node = SingleLinkedListDemo.getLastIndexNode(list.head, 4);System.out.println("倒数第一个节点为:"+node);}}
运行结果:
③ 单链表的反转【腾讯面试题,有点难度】

思路说明:
public class SingleLinkedListDemo {//反转链表public static void reverseList(HeroNode head) {//当链表为空或1个节点时不进行反转if(head.next == null || head.next.next == null) {System.out.println("当前链表为空或有一个元素,无法反转!");return;}//设置其为当前指向节点HeroNode curNode = head.next;//设置其为当前指向节点的后一节点HeroNode nextNode = null;//设置一个反转的链表,用于存放之后遍历的链表HeroNode reversehead = new HeroNode(0, "", "");while(curNode!=null) {nextNode = curNode.next;//用于获取到当前节点cur后一个节点curNode.next = reversehead.next;//这段代码相当于将每次获取的节点从后往前存放reversehead.next = curNode;//用于保存存入到reverse后的节点curNode = nextNode;//让curNode获取到nextNode的值,就像向后遍历一样}head.next = reversehead.next;//将反转过后的链表接连到初始链表head上System.out.println("链表反转成功");System.out.println();}}
测试代码:
package LinkedList;public class SingleLinkedListDemo {public static void main(String[] args) {SingleLinkedList list = new SingleLinkedList();//创建四个节点HeroNode node1 = new HeroNode(1, "丁明", "青龙偃妈刀");HeroNode node2 = new HeroNode(2, "小殷", "优雅男神");HeroNode node3 = new HeroNode(3, "单泽鹏", "马尾小萝莉");HeroNode node4 = new HeroNode(4, "顾天乐", "金刚小铁拳");//进行添加操作 这里是按照id进行添加的list.addNodeById(node3);list.addNodeById(node2);list.addNodeById(node1);list.addNodeById(node4);//进行遍历链表System.out.println("进行遍历链表:");list.showList();System.out.println();//链表进行反转操作reverseList(list.head);System.out.println("链表反转之后:");list.showList();}}
运行结果:
④ 从尾到头打印单链表 【百度,要求方式 1:反向遍历 。 方式 2:Stack 栈】
思路分析:
这里演示方式2:使用栈进行存储再打印
package LinkedList;import java.util.Stack;public class SingleLinkedListDemo {//将链表从后往前打印//使用到栈public static void reversedPrint(HeroNode head) {//判断链表是否为空if(head.next == null) {System.out.println("链表为空,无法打印");return;}//设置一个辅助节点HeroNode cur = head.next;//使用栈的apiStack<HeroNode> stack = new Stack<HeroNode>();while(cur != null) {stack.add(cur);//链表不断向后遍历,并压入栈cur = cur.next;}//进行遍历栈while(stack.size()>0) {System.out.println(stack.pop());}}}
测试过程:
说明:在遍历链表过程中不断存入栈中,最后再遍历栈中的数据,这样能够使链表的结构不变化**
package LinkedList;import java.util.Stack;public class SingleLinkedListDemo {public static void main(String[] args) {SingleLinkedList list = new SingleLinkedList();//创建四个节点HeroNode node1 = new HeroNode(1, "丁明", "青龙偃妈刀");HeroNode node2 = new HeroNode(2, "小殷", "优雅男神");HeroNode node3 = new HeroNode(3, "单泽鹏", "马尾小萝莉");HeroNode node4 = new HeroNode(4, "顾天乐", "金刚小铁拳");//进行添加操作 这里是按照id进行添加的list.addNode(node3);list.addNode(node2);list.addNode(node1);list.addNode(node4);//进行遍历链表System.out.println("进行遍历链表:");list.showList();System.out.println();//将链表从后往前打印输出System.out.println("链表从后往前打印:");SingleLinkedListDemo.reversedPrint(list.head);}}
运行结果:
四、双向链表的应用实例
源代码:DoubleLinkedListDemo.java
**
思路分析(双向链表与单链表的不同)

代码实现
说明:此次代码实现了增加节点(顺序)、增加节点(按照id小到大)、删除节点、更改节点、遍历链表、获取头节点。
有无变化说明
对于遍历节点、修改节点对于单链表都没有变化。
有变化的说明:
① 增加节点(顺序):需要给新增节点的pre赋值
② 增加节点(按照id):由单链表给两个next赋值改变为两个pre以及两个next,并且对于temp.next.pre这个节点的pre在链表最后位置添加时要注意空指针的情况,所以要加上判断。
③ 删除节点:单链表需要查找删除节点的前一个节点,而双链表可以直接查找到对应节点利用pre进行删除节点,对于获取到temp.next.pre也要进行null值判断进行赋值。
package LinkedList;public class DoubleLinkedListDemo {public static void main(String[] args) {DoubleLinkedList list = new DoubleLinkedList();//创建四个节点HeroNode2 node1 = new HeroNode2(1, "丁明", "青龙偃妈刀");HeroNode2 node2 = new HeroNode2(2, "小殷", "优雅男神");HeroNode2 node3 = new HeroNode2(3, "单泽鹏", "马尾小萝莉");HeroNode2 node4 = new HeroNode2(4, "顾天乐", "金刚小铁拳");//进行添加操作 这里是按照id进行添加的list.addNode(node1);list.addNode(node2);list.addNode(node3);list.addNode(node4);System.out.println("进行修改操作:");HeroNode2 node5 = new HeroNode2(3, "长路", "无敌拳霸");list.updateNode(node5);//进行遍历操作list.showList();System.out.println();System.out.println("进行删除操作:");list.delNode(4);list.showList();System.out.println();System.out.println("进行插入(根据id)操作:");list.addNodeById(new HeroNode2(0, "林儿", "长路对象"));list.showList();}}//创建管理链表的类class DoubleLinkedList{//先初始化一个头节点, 头节点不要动, 不存放具体的数据public HeroNode2 head = new HeroNode2(0, "", "");//返回头节点public HeroNode2 getHeadNode() {return head;}//进行添加节点到末尾public void addNode(HeroNode2 node) {//首先使用一个临时变量代替headHeroNode2 temp = head;//寻找到链表的最底部while(true) {if(temp.next == null) {break;}temp = temp.next;}//插入node节点到最底部temp.next = node;//增加点:将最后添加的节点的pre得到temp节点node.pre = temp;}//插入节点按照id编号排序进行插入public void addNodeById(HeroNode2 node) {//temp就代表待插入节点的前一个节点HeroNode2 temp = head;//这个flag代表是否有相同id值,true表示不能插入,false表示能插入boolean flag = false;while(true) {//当temp节点的下一个节点为null,说明在尾部了,跳出循坏在尾部添加if(temp.next == null) {break;}//当temp节点下一个节点的id与待插入节点的id相同,flag设置为true,表明不能插入if(temp.next.id == node.id) {flag = true;break;}//当temp节点下一个节点的id大于待插入节点id,跳出循环,将node节点插入到temp之后if(temp.next.id > node.id) {break;}//方便进行遍历temp = temp.next;}if(flag) {System.out.printf("插入的节点id【%d】已存在,无法插入\n",node.id);}else {if(temp.next != null) {//若不是最后一个节点,那么就可以获取到temp.next并赋值temp.next.pre = node;}//首先插入节点的next先获取到temp的next节点node.next = temp.next;//插入的节点的前一个节点为tempnode.pre = temp;//再将node节点插入到temp节点之前temp.next = node;}}//遍历链表public void showList() {//判断链表是否为空if(head.next == null) {System.out.println("链表为空,无法进行遍历数据!");return;}//使用一个临时变量获取到链表下一个节点HeroNode2 temp = head.next;while(true) {if(temp == null) {break;}System.out.println(temp);temp = temp.next;}}// 修改节点,根据id编号进行修改public void updateNode(HeroNode2 newnode) {// 创建一个辅助节点,令temp为head的nextHeroNode2 temp = head.next;// 判断是否为空链表情况if (temp == null) {System.out.println("链表为空,无法进行修改!");return;}// true表示能够修改, false表示不能修改boolean flag = false;while (true) {// 表示到达链表末尾,无法进行插入if (temp == null) {break;}// 找到对应id相同的英雄if (temp.id == newnode.id) {flag = true;// 表示能够进行修改break;}// 进行遍历使用temp = temp.next;}if (flag) {temp.name = newnode.name;temp.nickname = newnode.nickname;System.out.printf("修改id【%d】成功!\n",newnode.id);} else {System.out.println("链表中无法找到对应id英雄,修改失败!");}}//根据id来删除节点 由于是双向链表就可以查找对应要删除的节点即可进行删除public void delNode(int id) {if(head.next == null) {System.out.println("链表为空,无法删除!");return;}//直接获取到头节点的下一个节点HeroNode2 temp = head.next;//true用来表示找到删除的节点,false表示未找到删除的节点boolean flag = false;while(true) {//到链表末尾没有找到对应节点if(temp == null) {break;}//找到temp的下一节点为对应删除的节点if(temp.id == id) {flag = true;break;}//进行遍历temp = temp.next;}if(flag) {//删除节点的前一个节点的next为下一个节点temp.pre.next = temp.next;//为删除节点的后一个节点的pre赋值//避免删除项是最后一个节点的情况if(temp.next != null) {temp.next.pre = temp.pre;}System.out.printf("成功删除id【%d】",id);System.out.println();}else {System.out.printf("链表中未找到对应id【%d】节点,删除失败!",id);System.out.println();}}}//创建节点class HeroNode2{public int id;public String name;public String nickname;public HeroNode2 next;//指向后面一个节点public HeroNode2 pre;//指向前面一个节点//创建一个构造器,存放id、name、nicknamepublic HeroNode2(int id, String name, String nickname) {super();this.id = id;this.name = name;this.nickname = nickname;}@Overridepublic String toString() {return "HeroNode2 [id=" + id + ", name=" + name + ", nickname=" + nickname + "]";}}
运行结果:
五、单向环形链表
1. 单向环形链表应用场景

2. 单向环形链表介绍
源代码:Josepfo.java
示意图:
① Josephu 问题
问题描述:

② 构建约瑟夫环以及遍历约瑟夫环(代码实现)

创建约瑟夫环的节点以及约瑟夫环对象
//表示约瑟夫环class CircleSingleLinkedList{//需要创建第一个节点private Boy first = null;}class Boy{private Integer id;private Boy next;public Boy(Integer id) {super();this.id = id;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Boy getNext() {return next;}public void setNext(Boy next) {this.next = next;}}
创建约瑟夫环
说明:对于插入有两种情况,第一种是插入第一个节点时,第二种就是插入第二个节点之后所有节点。
需要的节点:**每次插入时创建的节点以及辅助节点(用于指向新创建的节点位置,不对first节点进行更改)。
//表示约瑟夫环class CircleSingleLinkedList{//需要创建第一个节点private Boy first = null;public void createJosepho(int num) {//对创建个数进行规范if(num<1) {System.out.println("创建人数过少,请重新创建!");return;}//创建一个辅助节点Boy curBoy = null;//进行循环插入for(int i=1;i<=num;i++) {Boy boy = new Boy(i);//如果是第一个创建的if(i == 1) {first = boy;first.setNext(first);//辅助节点获取到新插入的节点curBoy = first;}else {//不是第一次插入时根据辅助节点插入curBoy.setNext(boy);boy.setNext(first);curBoy = boy;}}System.out.printf("%d人的约瑟夫环创建成功\n",num);}}
遍历约瑟夫环
说明:**需要判断链表是否为空以及使用辅助节点来进行遍历,遍历时的条件是当前节点的下一个节点为first第一个节点时遍历结束。
//进行遍历约瑟夫环public void showJosepho() {//判断是否为空if(first == null) {System.out.println("约瑟夫环为空,无法遍历!");return;}//使用辅助节点来进行遍历Boy curBoy = first;while(true) {System.out.println("id:"+ curBoy.getId());if(curBoy.getNext() == first) {break;}curBoy = curBoy.getNext();}}
测试创建与遍历
package LinkedList;public class Josepfo {public static void main(String[] args) {//创建数量为5的约瑟夫环CircleSingleLinkedList list = new CircleSingleLinkedList();list.createJosepho(5);list.showJosepho();}}
运行结果:
③ 小孩出圈(传入初始位置、数数数量、总人数)

说明:接连在上面方法的类中,由于是单向链表,所以我们在出圈过程中还应该知晓出圈节点的前一个节点
① **初步状态辅助节点在整个环形链表最后。
② 根据初始位置来调整helper、first节点位置,始终一前一后状态。
③ 来根据数数进行出圈报出id名。**
public void countBoy(int startNo,int countNum,int nums) {//如果链表为空,初始位置小于1,初始位置大于总数if(startNo<1 || startNo>nums || first == null) {System.out.println("您输入的参数有误,请重新输入!");}//定义一个辅助节点Boy helper = first;//将辅助节点变为最后一个节点来紧跟first头节点while(true) {if(helper.getNext() == first) {break;}helper = helper.getNext();}//根据初始位置进行调位for(int i = 0;i<startNo-1;i++) {//两个节点一起移动first = first.getNext();helper = helper.getNext();}while(true) {//如果环中只有一个节点了,那么退出循环if(helper == first) {break;}//进行数数for(int i=0;i<countNum-1;i++) {first = first.getNext();helper = helper.getNext();}//将first指定的移除System.out.println("移除的id为:"+first.getId());first = first.getNext();//这里first移到移除人的后方helper.setNext(first);//辅助节点的next值指向新的first}System.out.println("最后一位id为:"+first.getId());}
测试代码:
package LinkedList;public class Josepfo {public static void main(String[] args) {//创建数量为5的约瑟夫环CircleSingleLinkedList list = new CircleSingleLinkedList();list.createJosepho(5);list.showJosepho();//起始位置为1,报数为2,总人数为5System.out.printf("\n开始数数了:\n");list.countBoy(1, 2, 5);}}
运行结果:
整理者:长路 时间:?-2020/8/6
