实现类:
package demo03_LinkedList;
import java.util.Iterator;
public class CircleSingleLinkedList<T> implements Iterable<T> {
private Node<T> first;
private Node<T> last;
private int size = 0;
public CircleSingleLinkedList() {
}
public CircleSingleLinkedList(T elem) {
this.first = new Node<>();
first.temp = elem;
first.next = first;
last = first;
size++;
}
// 添加元素
public void add(T elem) {
if (size == 0) {
first = new Node<>();
first.temp = elem;
first.next = first;
last = first;
size++;
} else {
Node<T> node = new Node<>();
last.next = node;
node.temp = elem;
node.next = first;
last = node;
size++;
}
}
// 根据先进先出原则删除元素,并返回被删除的元素
public T getQueue() {
if (size == 0)
throw new RuntimeException("空链表,无法删除元素");
T elem = first.temp;
if (size == 1) {
first = last = null;
size--;
return elem;
}
first = first.next;
last.next = first;
size--;
return elem;
}
// 根据后进先出原则删除元素,并返回被删除的元素
public T getStack() {
if (size == 0)
throw new RuntimeException("空链表,无法删除元素");
T elem = last.temp;
Node<T> previous = getPrevious(first);
if (previous == last) { // 只有一个结点
last = first = null;
size--;
return elem;
}
previous.next = first;
last.next = null;
last = previous;
size--;
return elem;
}
// 返回当前链表last结点的前一位结点
private Node<T> getPrevious(Node<T> node) {
Node<T> previous = node;
if (previous.next == last) {
return previous;
} else {
previous = previous.next;
return getPrevious(previous);
}
}
// 修改链表中第一个检索到的指定元素值为想要修改成的指定值,并返回被修改的元素
public T alterElement(T beforeElem, T afterElem) {
Node<T> node = searchNode(beforeElem);
T elem = node.temp;
node.temp = afterElem;
return elem;
}
// 根据指定值查找链表信息,返回检索到的第一个指定值所在的结点
public Node<T> searchNode(T elem) {
if (size == 0)
throw new RuntimeException("空链表");
Node<T> node = first;
while (true) {
if (elem.equals(node.temp))
return node;
if (node.next == first)
break;
node = node.next;
}
throw new RuntimeException("链表中不存在指定值");
}
// 判断是否包含指定元素
public boolean contains(T elem) {
if (size == 0)
throw new RuntimeException("空链表");
Node<T> node = first;
while (true) {
if (elem.equals(node.temp))
return true;
if (node.next == first)
break;
node = node.next;
}
return false;
}
// 获取链表中最先放入链表的元素
public T getFirstElement(){
return first.temp;
}
// 获取链表中最后放入链表的元素
public T getLastElement(){
return last.temp;
}
// 判空
public boolean isEmpty() {
return size == 0;
}
// 获取链表中元素数量
public int getSize() {
return size;
}
public Node<T> getFirst() {
return first;
}
public void setFirst(Node<T> first) {
this.first = first;
}
public Node<T> getLast() {
return last;
}
public void setLast(Node<T> last) {
this.last = last;
}
@Override
public String toString() {
StringBuilder str = new StringBuilder();
str.append("Link = {");
Node<T> node = first;
while (true) {
if (node == null)
break;
if (node.next == first) {
str.append(node.temp);
break;
}
str.append(node.temp + ",");
node = node.next;
}
str.append("} -- size = " + size);
return str.toString();
}
// 后进先出迭代器
public Iterator<T> stackIterator() {
return new StackIterator();
}
// 后进先出迭代器封装内部类
private class StackIterator implements Iterator<T> {
private Node<T> newFirst = first;
private Node<T> newLast = last;
private int n = size;
private T elem = null;
@Override
public boolean hasNext() {
return n != 0;
}
@Override
public T next() {
elem = newLast.temp;
newLast = getStackPrevious(newFirst);
n--;
return elem;
}
public Node<T> getStackPrevious(Node<T> node){
Node<T> previous = node;
if (previous.next == newLast){
return previous;
}else {
previous = previous.next;
return getStackPrevious(previous);
}
}
}
// 先进先出迭代,支持增强for
@Override
public Iterator<T> iterator() {
return new QueueIterator();
}
//先进先出迭代器内部类
private class QueueIterator implements Iterator<T> {
private Node<T> node = first;
private int n = size;
@Override
public boolean hasNext() {
return n != 0;
}
@Override
public T next() {
T elem = node.temp;
node = node.next;
n--;
return elem;
}
}
// 结点类
private class Node<T> {
private T temp;
private Node<T> next;
}
/**
* 约瑟夫问题解决方案:
* start: 表示从第几个小孩开始数(k)
* count: 表示要数几下(m)
*/
public static <T> void countBoy(CircleSingleLinkedList<T> link, int start, int count) {
// 判断参数是否符合要求
if (link.size == 0 || start < 1 || start > link.size || count <= 0) {
System.out.println("参数输入有误,请重新输入");
return;
}
// 打印参与游戏小孩信息
System.out.println("参与做游戏的小孩及其编号为:");
System.out.println(link.toString());
// 将指针移动到起始报数位置
for (int i = 1; i < start; i++) {
link.first = link.first.next;
link.last = link.last.next;
}
int cnt = 0;
T temp = null;
System.out.println("游戏开始:");
while (link.size > 0) {
if (link.first == link.last) {
temp = link.first.temp;
link.first = link.last = null;
link.size--;
cnt++;
System.out.printf("第%d次,%s出圈了!\n", cnt, temp);
} else {
// 将指针移动到报数完毕的小孩位置
for (int i = 1; i < count; i++) {
link.first = link.first.next;
link.last = link.last.next;
}
// 小孩出圈(从链表中移除最后报数的小孩)
temp = link.first.temp;
link.last.next = link.first.next;
link.first = link.first.next;
link.size--;
cnt++;
System.out.printf("第%d次,%s出圈了!\n", cnt, temp);
}
}
System.out.printf("参与游戏的小孩还有%d个,游戏结束!", link.size);
}
/**
* 创建单向循环链表
* num: 链表中包含的元素个数
* clazz: 链表中存储元素类型的类
*/
public static CircleSingleLinkedList creatLink(int num, Class clazz) {
CircleSingleLinkedList link = new CircleSingleLinkedList();
for (int i = 1; i < num + 1; i++) {
try {
// 利用反射获取构造函数
Constructor constructor = clazz.getConstructor(int.class);
Object boy = constructor.newInstance(i);
link.add(boy);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return link;
}
}
测试类:
package demo03_LinkedList;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
CircleSingleLinkedList<Integer> link = new CircleSingleLinkedList<>();
try {
for (int i = 1; i < 11; i++) {
link.add(i);
}
System.out.println(link.toString());
int length = link.getSize();
System.out.println("按照先进先出原则删除元素:");
for (int i = 0; i < length ; i++) {
Integer integer = link.getQueue();
System.out.print(integer + " ");
}
System.out.println();
for (int i = 1; i < 11; i++) {
link.add(i);
}
System.out.println(link.toString());
System.out.println("按照后进先出原则删除元素:");
for (int i = 0; i < length; i++) {
System.out.print(link.getStack() + " ");
}
System.out.println();
for (int i = 1; i < 11; i++) {
link.add(i);
}
System.out.println("先进先出迭代:");
for (Integer integer : link) {
System.out.print(integer + " ");
}
System.out.println();
System.out.println("后进先出迭代:");
Iterator<Integer> it = link.stackIterator();
while (it.hasNext()){
System.out.print(it.next() + " ");
}
} catch (RuntimeException e) {
e.printStackTrace();
}finally {
}
}
}
测试结果:
Link = {1,2,3,4,5,6,7,8,9,10} -- size = 10
按照先进先出原则删除元素:
1 2 3 4 5 6 7 8 9 10
Link = {1,2,3,4,5,6,7,8,9,10} -- size = 10
按照后进先出原则删除元素:
10 9 8 7 6 5 4 3 2 1
先进先出迭代:
1 2 3 4 5 6 7 8 9 10
后进先出迭代:
10 9 8 7 6 5 4 3 2 1
Joseph(约瑟夫)问题:
设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数到m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
代码:
/**
* 约瑟夫问题解决方案:
* start: 表示从第几个小孩开始数(k)
* count: 表示要数几下(m)
*/
public static <T> void countBoy(CircleSingleLinkedList<T> link, int start, int count) {
// 判断参数是否符合要求
if (link.size == 0 || start < 1 || start > link.size || count <= 0) {
System.out.println("参数输入有误,请重新输入");
return;
}
// 打印参与游戏小孩信息
System.out.println("参与做游戏的小孩及其编号为:");
System.out.println(link.toString());
// 将指针移动到起始报数位置
for (int i = 1; i < start; i++) {
link.first = link.first.next;
link.last = link.last.next;
}
int cnt = 0;
T temp = null;
System.out.println("游戏开始:");
while (link.size > 0) {
if (link.first == link.last) {
temp = link.first.temp;
link.first = link.last = null;
link.size--;
cnt++;
System.out.printf("第%d次,%s出圈了!\n", cnt, temp);
} else {
// 将指针移动到报数完毕的小孩位置
for (int i = 1; i < count; i++) {
link.first = link.first.next;
link.last = link.last.next;
}
// 小孩出圈(从链表中移除最后报数的小孩)
temp = link.first.temp;
link.last.next = link.first.next;
link.first = link.first.next;
link.size--;
cnt++;
System.out.printf("第%d次,%s出圈了!\n", cnt, temp);
}
}
System.out.printf("参与游戏的小孩还有%d个,游戏结束!", link.size);
}
/**
* 创建单向循环链表
* num: 链表中包含的元素个数
* clazz: 链表中存储元素类型的类
*/
public static CircleSingleLinkedList creatLink(int num, Class clazz) {
CircleSingleLinkedList link = new CircleSingleLinkedList();
for (int i = 1; i < num + 1; i++) {
try {
// 利用反射获取构造函数
Constructor constructor = clazz.getConstructor(int.class);
Object boy = constructor.newInstance(i);
link.add(boy);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return link;
}
测试:
package demo03_LinkedList;
import java.util.Scanner;
public class JosephTest {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入参与游戏的小孩数量:");
int num = sc.nextInt();
CircleSingleLinkedList link = CircleSingleLinkedList.creatLink(num, Boy.class);
System.out.println("请输入起始报数小孩编号:");
int start = sc.nextInt();
System.out.println("请输入报数次数:");
int count = sc.nextInt();
CircleSingleLinkedList.countBoy(link, start, count);
}
}
class Boy {
private int num;
public Boy() {
}
public Boy(int num) {
this.num = num;
}
@Override
public String toString() {
return "Boy" + num;
}
}
测试结果:
请输入参与游戏的小孩数量:
5
请输入起始报数小孩编号:
1
请输入报数次数:
2
参与做游戏的小孩及其编号为:
Link = {Boy1,Boy2,Boy3,Boy4,Boy5} -- size = 5
游戏开始:
第1次,Boy2出圈了!
第2次,Boy4出圈了!
第3次,Boy1出圈了!
第4次,Boy5出圈了!
第5次,Boy3出圈了!
参与游戏的小孩还有0个,游戏结束!
来源:CSDN
作者:是筱鱼呀
链接:https://blog.csdn.net/Sunhongzhe/article/details/103882483