关于链表的新三中形式,环形链表的介绍和代码实现
1 环形链表
1.1 约瑟夫问题
- 约瑟夫(Josephu)问题:
- 设置编号为1,2,3…n个人围坐一圈,约定编号为k(1<=k<=n)的人开始报数,数到m个那个人出列,以此类推,直到所有人都出列,产生一个出队编号序列
- 解决问题:使用环形链表解决
1.2 单向环形链表
1.3 单向环形链表思路
- (1)添加数据
- 创建两个变量,firstNode(第一个节点),curNode(当前最新节点)
- 第一次添加node时,firstNode指向该node,curnode也指向该node,node自身next指向自己形成环状
- 后续添加node时,
curNode.next == node,node.next == firstNode
,形成环状,并将curNode == node
- (2)遍历数据
- 创建临时node指向firstNode,依次next遍历数据,直到emp.next = first结束循环
1.4 单向环形代码实现
- (1)代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57public class SingleCircularLinkedList {
//单向节点类
private class Node {
public Object data;
public Node next;
public Node(Object data) {
this.data = data;
}
public String toString() {
return "Node{ data = " + data + " }";
}
}
private Node firstNode; //第一个节点
private Node curNode; //最新一个节点
/**
* 添加数据
* @param data 数据
*/
public void add(Object data) {
Node node = new Node(data);
//第一个数据firstNode 和 curNode需要特殊处理
if(firstNode == null) {
firstNode = node;
}
if(curNode != null) {
curNode.next = node;
}
node.next = firstNode;
curNode = node;
}
/**
* 打印单向环形列表
*/
public void print() {
Node temp = firstNode;
if (temp == null) {
System.out.println("链表为空");
return;
}
System.out.println("单向环形链表为:");
do {
System.out.println(temp);
temp = temp.next;
}while(temp != firstNode);
}
}
- (2)测试
1
2
3
4
5
6
7
8
9
public void SingleCircularLinkedListTest() {
//1. 创建单向环形链表
SingleCircularLinkedList linkedList = new SingleCircularLinkedList();
linkedList.add(1);
linkedList.add(2);
linkedList.add(3);
linkedList.print();
}
1.5 约瑟夫问题解决
- (1)思路
- (1)数数,即将firstNode 和 CurNode进行移动,移动m-1次,此时firstNode的位置为出队列位置
- (2)出队列:接将节点删除,直接firstNode向后移(firstNode = firstNode.next),并curNode断开出列节点的指向(curNode.next = first)
- (2)代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30/**
* 打印约瑟夫问题队列
* @param start 开始位置
* @param num 间隔
*/
public void josephuQueue(int start, int num) {
//移动位置
int count = 1;
while(count != start) {
firstNode = firstNode.next;
curNode = curNode.next;
count ++;
}
System.out.println("约瑟夫问题队列为:");
while (curNode != firstNode) {
count = 1;
//循环报数
while(count != num) {
firstNode = firstNode.next;
curNode = curNode.next;
count ++;
}
//出列(删除节点并打印)
System.out.println(firstNode);
firstNode = firstNode.next;
curNode.next = firstNode;
}
System.out.println(firstNode);
}
- (3)测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void SingleCircularLinkedListTest() {
//1. 创建单向环形链表
SingleCircularLinkedList linkedList = new SingleCircularLinkedList();
linkedList.add(1);
linkedList.add(2);
linkedList.add(3);
linkedList.add(4);
linkedList.add(5);
linkedList.print();
//2. josephu问题
linkedList.josephuQueue(1, 2);
}