【数据结构与算法(Java)】单向环形链表(按顺序添加)

1. 应用场景

2. 思路

  • 节点结构
    • 数据域(Data):存储 当前节点数据
    • 地址域1(Next):指向 下一个节点地址
  • 环形链表结构
    • 头节点:储存环形链表的第一个节点
    • 储存方式:尾部节点指向头节点
    • 不一定 是连续存储
    • 添加节点:本文章按照直接添加到尾节点的方式
      在这里插入图片描述

3. 数据结构(类结构):

【节点 SingleNode】

(1)成员变量(Field)

  • data: int,节点所储存的数据
  • nextNode: SingleNode,所指向的下一个节点
    private int data;
    private SingleNode nextNode;

(2)初始化 / 构造器(Constructor)

  • 参数传入节点所要储存的数据
  • 初始化节点数据
    public SingleNode(int data) {
        this.data = data;
    }

(3)方法(Methods)

- 两个成员变量的getter和setter
    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public SingleNode getNextNode() {
        return nextNode;
    }

    public void setNextNode(SingleNode nextNode) {
        this.nextNode = nextNode;
    }
- toString方法
    @Override
    public String toString() {
        return "SingleNode{" +
                "data=" + data +
                '}';
    }

【单向环形链表 CircleSingleLinkedList】

(1)成员变量(Field)

  • firstNode: 头节点,指向链表的第一个节点
    private SingleNode firstNode;

(2)初始化 / 构造器(Constructor)

  • 默认构造器

(3)方法(Methods)

- 批量添加新节点

initializeForJoseph(int) -> void

    /**
     * 添加 number 个节点到环形链表, 编号为 1 ~ number(为约瑟夫问题作准备)
     * @param number - 待添加的节点数
     */
    public void initializeForJoseph(int number) {
        // 若链表不为空,将其变为空
        if (this.firstNode != null) {
            this.firstNode = null;
        }

        // 循环创造number个新节点,数值为 1~number,逐个加入环形链表
        SingleNodePractice currentNode = null;
        for (int i = 1; i <= number; i++) {
            SingleNodePractice newNode = new SingleNodePractice(i);
            if (this.firstNode == null) {
                this.firstNode = newNode;
            } else {
                currentNode.setNextNode(newNode);
            }
            currentNode = newNode;
        }
        currentNode.setNextNode(this.firstNode);
    }
- 查找某节点是否存在

isNodeExist(SingleNode) -> boolean

    /**
     * 查找所给节点是否存在于环形链表
     * @param node - 待查找节点
     * @return - boolean,是否找到节点
     */
    public boolean isNodeExist(SingleNode node) {
        // 1. 若链表为空,抛出异常
        if (this.firstNode == null) {
            throw new RuntimeException("empty!");
        }

        // 2. 遍历查找所给节点,若存在则found为true退出循环
        // 2.1 设置boolean变量found
        boolean found = false;
        // 2.2 设置当前节点变量
        SingleNode currentNode = this.firstNode;
        // 2.3 遍历,逐个判断所给节点值和链表中的节点值,相等时找到,设found为true,退出循环
        while (true) {
            // (1) 若相等,找到,found为true,退出循环
            if (currentNode.getData() == node.getData()) {
                found = true;
                break;
            }
            // (2) 若下一节点为首节点,到末尾,退出循环
            if (currentNode.getNextNode() == this.firstNode) {
                break;
            }
            // (3) 移动当前节点到下一节点
            currentNode = currentNode.getNextNode();
        }

        // 3. 返回found值
        return found;
    }
- 获取全部节点的计数

countNodes() -> int

    /**
     * 统计环形链表的有效节点数
     * @return int - 节点数
     */
    public int countNodes() {
        // 设置辅助int变量count
        int count = 0;

        // 若链表不为空,遍历并统计有效节点数
        if (this.firstNode != null) {
            // 设置辅助节点变量,储存当前节点
            SingleNode currentNode = this.firstNode;
            // 遍历整个链表,统计节点数
            while (true) {
                // count加1
                count++;
                // 若当前节点的next为首节点,到达末尾,结束循环
                if (currentNode.getNextNode() == this.firstNode) {
                    break;
                }
                // 移动当前节点到下一位
                currentNode = currentNode.getNextNode();
            }
        }

        // 返回count
        return count;
    }

- 打印全部节点的数据

displayAllNodes() -> void

    /**
     * 打印全部节点值
     */
    public void displayAllNodes() {
        // 1. 若首节点为null,则链表为空,抛出异常
        if (this.firstNode == null) {
            throw new RuntimeException("The list is empty!");
        }

        // 2. 遍历,打印每个节点值
        // 2.1 设置current节点
        SingleNode currentNode = this.firstNode;
        // 2.2 遍历,打印当前节点值,到末尾停止
        while (true) {
            // (1) 打印当前节点值
            System.out.println(currentNode.toString());
            // (2) 若当前节点值的下一节点为首节点,则到达末尾,结束循环
            if (currentNode.getNextNode() == this.firstNode){
                break;
            }
            // (3) 移动当前节点到下一节点
            currentNode = currentNode.getNextNode();
        }
    }

4. 完整实现

public class CircleSingleLinkedList {
    private SingleNode firstNode;

    /**
     * 添加 number 个节点到环形链表, 编号为 1 ~ number(为约瑟夫问题作准备)
     * @param number - 待添加的节点数
     */
    public void initializeForJoseph(int number) {
        // 若链表不为空,将其变为空
        if (this.firstNode != null) {
            this.firstNode = null;
        }

        // 循环创造number个新节点,数值为 1~number,逐个加入环形链表
        SingleNodePractice currentNode = null;
        for (int i = 1; i <= number; i++) {
            SingleNodePractice newNode = new SingleNodePractice(i);
            if (this.firstNode == null) {
                this.firstNode = newNode;
            } else {
                currentNode.setNextNode(newNode);
            }
            currentNode = newNode;
        }
        currentNode.setNextNode(this.firstNode);
    }
    
    /**
     * 打印全部节点值
     */
    public void displayAllNodes() {
        // 1. 若首节点为null,则链表为空,抛出异常
        if (this.firstNode == null) {
            throw new RuntimeException("The list is empty!");
        }

        // 2. 遍历,打印每个节点值
        // 2.1 设置current节点
        SingleNode currentNode = this.firstNode;
        // 2.2 遍历,打印当前节点值,到末尾停止
        while (true) {
            // (1) 打印当前节点值
            System.out.println(currentNode.toString());
            // (2) 若当前节点值的下一节点为首节点,则到达末尾,结束循环
            if (currentNode.getNextNode() == this.firstNode){
                break;
            }
            // (3) 移动当前节点到下一节点
            currentNode = currentNode.getNextNode();
        }
    }

    /**
     * 查找所给节点是否存在于环形链表
     * @param node - 待查找节点
     * @return - boolean,是否找到节点
     */
    public boolean isNodeExist(SingleNode node) {
        // 1. 若链表为空,抛出异常
        if (this.firstNode == null) {
            throw new RuntimeException("empty!");
        }

        // 2. 遍历查找所给节点,若存在则found为true退出循环
        // 2.1 设置boolean变量found
        boolean found = false;
        // 2.2 设置当前节点变量
        SingleNode currentNode = this.firstNode;
        // 2.3 遍历,逐个判断所给节点值和链表中的节点值,相等时找到,设found为true,退出循环
        while (true) {
            // (1) 若相等,找到,found为true,退出循环
            if (currentNode.getData() == node.getData()) {
                found = true;
                break;
            }
            // (2) 若下一节点为首节点,到末尾,退出循环
            if (currentNode.getNextNode() == this.firstNode) {
                break;
            }
            // (3) 移动当前节点到下一节点
            currentNode = currentNode.getNextNode();
        }

        // 3. 返回found值
        return found;
    }

    /**
     * 统计环形链表的有效节点数
     * @return int - 节点数
     */
    public int countNodes() {
        // 设置辅助int变量count
        int count = 0;

        // 若链表不为空,遍历并统计有效节点数
        if (this.firstNode != null) {
            // 设置辅助节点变量,储存当前节点
            SingleNode currentNode = this.firstNode;
            // 遍历整个链表,统计节点数
            while (true) {
                // count加1
                count++;
                // 若当前节点的next为首节点,到达末尾,结束循环
                if (currentNode.getNextNode() == this.firstNode) {
                    break;
                }
                // 移动当前节点到下一位
                currentNode = currentNode.getNextNode();
            }
        }

        // 返回count
        return count;
    }


    public SingleNode getFirstNode() {
        return firstNode;
    }

    public void setFirstNode(SingleNode firstNode) {
        this.firstNode = firstNode;
    }
}

class SingleNode {
    private int data;
    private SingleNode nextNode;

    public SingleNode(int data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "SingleNode{" +
                "data=" + data +
                '}';
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public SingleNode getNextNode() {
        return nextNode;
    }

    public void setNextNode(SingleNode nextNode) {
        this.nextNode = nextNode;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值