Java单向循环链表&解决约瑟夫环问题

单向循环链表

解决约瑟夫环问题

1.构造方法 及字段
public CircleLinkedList() {
    }
    /**
     * 链表的第一个节点
     */
    private Node first;
2.获取有效节点数
/**
 * 获取节点数
 */
public int elementsCount() {
    int result = 0;
    for (Node currentNode = this.first; ; currentNode = currentNode.next) {
        result++;
        if (currentNode.next == this.first)
            break;
    }
    return result;
}
3.判断循环链表是否为空
/**
 * 约瑟夫是否为空
 *
 * @return 是否为空
 */
public boolean isEmpty() {
    return this.first == null;
}
4.获取倒数第一个节点和倒数第二个节点
 /**
     * 获取倒数第二个节点
     *
     * @return
     */
    public Node getBeforeNode(int offset) {
        Node currentNode = first;
        while (currentNode.next != this.getIndexNode(offset)) {
            currentNode = currentNode.next;
        }
        return currentNode;
    }

    /**
     * 获取最后一个节点
     */
    public Node getLastNode() {
        Node currentNode = first;
        while (currentNode.next != first) {
            currentNode = currentNode.next;
        }
        //for(currentNode=this.first;currentNode.next!=this.first;currentNode=currentNode.next);
        return currentNode;
    }

5.添加新节点
/**
 * 添加新节点
 */
public void add(String item) {
    if (isEmpty()) {
        first = new Node(item);
        first.next = first;
        return;
    }
    Node node = new Node(item, this.first);
    Node lastNode = getLastNode();
    lastNode.next = node;


}
6.根据位置获取节点
/**
 * 根据位置去获取相应的节点
 */
public Node getIndexNode(int index) {
    if (index < 0 || index >= elementsCount())
        throw new IndexOutOfBoundsException("偏移量非法:" + index);
    Node result = this.first;
    for (int i = 0; i < index; i++) {
        result = result.next;
    }

    return result;
}
7.根据起始偏移量beginNo和间隔gap实现约瑟夫环的循环输出节点内容到字符串
/**
 * 所有元素出圈
 * @param beginNo 起始偏移量
 * @param gap 间隔
 * @return 结果
 */
public String[] getAll(int beginNo, int gap){
    /*
    参数校验和出圈的准备
     */
    if(this.first == null)
        System.out.println("链表为空无法完成出列。");
    int currentElementsCount = this.elementsCount();
    if(beginNo < 1 || beginNo > currentElementsCount)
        throw new IndexOutOfBoundsException("起始位置输入有误:" + beginNo);
    /*
    使用temp指向当前链表中最后一个节点
     */
    Node temp = this.getLastNode();
    /*
    使得first和temp移动beginNo - 1次
     */
    for(int i = 0; i < beginNo - 1; i ++){
        this.first = this.first.next;
        temp = temp.next;
    }

    //实例化这个数组,将用于存放依次出圈的节点值。
    String[] result = new String[currentElementsCount];
    int resultArrayIndex = 0;
    /*
    开始进行循环出圈
     */
    while (true) {
        //经过不断的元素出圈最终会使得helper和first指向了同一个节点。
        if(temp == this.first)
            break;
        //进行移动
        for (int i = 0; i < gap - 1; i ++){
            this.first = this.first.next;
            temp = temp.next;
        }
        //将被出圈的元素值存储到数组中。
        result[resultArrayIndex ++] = this.first.item;
        this.first = this.first.next;
        temp.next = this.first;
    }
    result[resultArrayIndex ++] = this.first.item;
    return result;
}
8.重写toString 方法,实现打印单向循环链表中的元素
 @Override
    public String toString() {
        if (isEmpty())
            return "[]";
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("[--");

        for (Node currentNode = this.first; ; currentNode = currentNode.next) {
            stringBuilder.append(currentNode.item);
            if (currentNode.next == this.first) {
                stringBuilder.append("--]");
                break;
            }
            stringBuilder.append(",");
        }
        return stringBuilder.toString();
    }


9.静态的节点内部类
/**
 * 节点类
 * 类似静态成员方法,可以通过类去调用
 */
public static class Node {
    public Node() {
    }

    public Node(String item) {
        this.item = item;
    }

    public Node(String item, Node next) {
        this.item = item;
        this.next = next;
    }

    /**
     * 节点存储值
     */
    private String item;

    /**
     * 后置节点
     */
    private Node next;

    /**
     * 获取节点内容
     */
    public String getItem() {
        return item;
    }
}
10.总体实现
package com.circle.util;

import java.util.Arrays;

public class CircleLinkedList {

    public CircleLinkedList() {
    }
    /**
     * 链表的第一个节点
     */
    private Node first;

    /**
     * 获取节点数
     */
    public int elementsCount() {
        int result = 0;
        for (Node currentNode = this.first; ; currentNode = currentNode.next) {
            result++;
            if (currentNode.next == this.first)
                break;
        }
        return result;
    }

    /**
     * 约瑟夫是否为空
     *
     * @return 是否为空
     */
    public boolean isEmpty() {
        return this.first == null;
    }

    /**
     * 获取倒数第二个节点
     *
     * @return
     */
    public Node getBeforeNode(int offset) {
        Node currentNode = first;
        while (currentNode.next != this.getIndexNode(offset)) {
            currentNode = currentNode.next;
        }
        return currentNode;
    }

    /**
     * 获取最后一个节点
     */
    public Node getLastNode() {
        Node currentNode = first;
        while (currentNode.next != first) {
            currentNode = currentNode.next;
        }
        //for(currentNode=this.first;currentNode.next!=this.first;currentNode=currentNode.next);
        return currentNode;
    }

    /**
     * 添加新节点
     */
    public void add(String item) {
        if (isEmpty()) {
            first = new Node(item);
            first.next = first;
            return;
        }
        Node node = new Node(item, this.first);
        Node lastNode = getLastNode();
        lastNode.next = node;


    }

    /**
     * 根据位置去获取相应的节点
     */
    public Node getIndexNode(int index) {
        if (index < 0 || index >= elementsCount())
            throw new IndexOutOfBoundsException("偏移量非法:" + index);
        Node result = this.first;
        for (int i = 0; i < index; i++) {
            result = result.next;
        }

        return result;
    }

    /**
     * 所有元素出圈
     * @param beginNo 起始偏移量
     * @param gap 间隔
     * @return 结果
     */
    public String[] getAll(int beginNo, int gap){
        /*
        参数校验和出圈的准备
         */
        if(this.first == null)
            System.out.println("链表为空无法完成出列。");
        int currentElementsCount = this.elementsCount();
        if(beginNo < 1 || beginNo > currentElementsCount)
            throw new IndexOutOfBoundsException("起始位置输入有误:" + beginNo);
        /*
        使用temp指向当前链表中最后一个节点
         */
        Node temp = this.getLastNode();
        /*
        使得first和temp移动beginNo - 1次
         */
        for(int i = 0; i < beginNo - 1; i ++){
            this.first = this.first.next;
            temp = temp.next;
        }

        //实例化这个数组,将用于存放依次出圈的节点值。
        String[] result = new String[currentElementsCount];
        int resultArrayIndex = 0;
        /*
        开始进行循环出圈
         */
        while (true) {
            //经过不断的元素出圈最终会使得helper和first指向了同一个节点。
            if(temp == this.first)
                break;
            //进行移动
            for (int i = 0; i < gap - 1; i ++){
                this.first = this.first.next;
                temp = temp.next;
            }
            //将被出圈的元素值存储到数组中。
            result[resultArrayIndex ++] = this.first.item;
            this.first = this.first.next;
            temp.next = this.first;
        }
        result[resultArrayIndex ++] = this.first.item;
        return result;
    }

    /**
     * 打印输出
     */
    public void print() {
        if (isEmpty())
            System.out.println("空");
        Node cntNode = this.first;
        while (cntNode.next != first) {
            System.out.println(cntNode.item);
            cntNode = cntNode.next;
        }
        System.out.println(cntNode.item);
    }

    @Override
    public String toString() {
        if (isEmpty())
            return "[]";
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("[--");

        for (Node currentNode = this.first; ; currentNode = currentNode.next) {
            stringBuilder.append(currentNode.item);
            if (currentNode.next == this.first) {
                stringBuilder.append("--]");
                break;
            }
            stringBuilder.append(",");
        }
        return stringBuilder.toString();
    }


    /**
     * 节点类
     * 类似静态成员方法,可以通过类去调用
     */
    public static class Node {
        public Node() {
        }

        public Node(String item) {
            this.item = item;
        }

        public Node(String item, Node next) {
            this.item = item;
            this.next = next;
        }

        /**
         * 节点存储值
         */
        private String item;

        /**
         * 后置节点
         */
        private Node next;

        /**
         * 获取节点内容
         */
        public String getItem() {
            return item;
        }
    }
}
11.测试类
package com.circle.test;

import com.circle.util.CircleLinkedList;

import java.util.Arrays;

public class Demo1 {
    public static void main(String[] args) {
        CircleLinkedList circleLinkedList = new CircleLinkedList();
        circleLinkedList.add("宫本1");
        circleLinkedList.add("宫本2");
        circleLinkedList.add("宫本3");
        circleLinkedList.add("宫本4");
        System.out.println("-------------");

        String[] strings = circleLinkedList.getAll(1,4);
        System.out.println(Arrays.toString(strings));



    }
}
输出结果:[宫本4, 宫本1, 宫本3, 宫本2];
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ILFFQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值