Java数据结构之环形单链表(带表头)的简单实现——day04

简介:在单向链表的基础上,实现环形单链表(带表头)

环形链表是单向链表的优化,可以用于解决Josephus问题。

这里创建三个类,分别是节点数据类NodeData、节点类Node、环形链表类CircularLinkedList,前面的文章已做过单链表的分析,故不再分析,直接给出代码,详见:Java数据结构之单链表——day03

1.NodeData类

package 环形链表;

import java.util.Objects;

/**
 * @Classname NodeData
 * @Description TODO
 * @Date 2022/5/8 15:06
 * @Created by jiawen
 */
public class NodeData {
    public int number;

    public NodeData() {
    }

    public NodeData(int number) {
        this.number = number;
    }


}

2.Node类

package 环形链表;

/**
 * @Classname Node
 * @Description TODO
 * @Date 2022/5/8 15:07
 * @Created by jiawen
 */
public class Node {
    public NodeData data;
    public Node nextNode;


    public Node(NodeData data) {
        this.data = data;

    }

    public Node(NodeData data, Node nextNode) {
        this.data = data;
        this.nextNode = nextNode;
    }

    @Override
    public String toString() {
        return "Node{" +
                "data=" + this.data.number +
                ", nextData=" + this.nextNode.data.number +
                '}';
    }
}

3. CircularLinkedList类

提供增、删、改、查、遍历、获取节点数等功能,如果想要链表中的数据可重复,请自行修改 NodeData的equals方法

package 环形链表;

/**
 * @Classname CircularLinkedList
 * @Description TODO
 * @Date 2022/5/8 15:09
 * @Created by jiawen
 */
public class CircularLinkedList {

    private Node initialNode = new Node(new NodeData(-1), null);//头节点


    public CircularLinkedList() {

    }

    public int getCount() {
        int count = 1;

        if (initialNode.nextNode == null) {
            System.out.println("Please insert your data,otherwise the count of the list will be 0 !");
            return 0;
        }
        Node temp = initialNode.nextNode;
        Node firstNode = initialNode.nextNode;
        while (true) {
            if (temp.nextNode.equals(firstNode)) {
                break;
            } else {
                temp = temp.nextNode;
                count++;

            }

        }
        return count;

    }

    public void addNode(NodeData nodeData) {
        Node toBeAded = new Node(nodeData);

        if (initialNode.nextNode == null) {
            initialNode.nextNode = toBeAded;
            toBeAded.nextNode = toBeAded;
            System.out.println("Insert initial data success!");
            return;

        }
        Node firstNode = initialNode.nextNode;
        Node finalNode = initialNode.nextNode;
        while (!finalNode.nextNode.equals(firstNode)) {
            finalNode = finalNode.nextNode;

        }
        finalNode.nextNode = toBeAded;
        toBeAded.nextNode = firstNode;

    }

    public void listAll() {

        if (initialNode.nextNode == null) {
            System.out.println("There is No data to list");
            return;
        }
        Node temp = initialNode.nextNode;
        Node first = initialNode.nextNode;
        while (!temp.nextNode.equals(first)) {
            System.out.println(temp);
            temp = temp.nextNode;
        }
        System.out.println(temp);//用于输出最后一个数据,没有的话就不会输出最后一个
        return;


    }

    public void dropNode(int number) {

        if (initialNode.nextNode == null) {
            System.out.println("There is no data to delete here!");
            return;
        }//首先判断list是不是空的,list为空则无法删除


        Node finalNode = initialNode.nextNode;//定义一个firstNode节点,在删除第一个数据时使用;
        Node temp = initialNode.nextNode;//定义一个指针temp,在要删除的数据不是第一个时使用;
        Node firstNode = initialNode.nextNode;//定义一个finalNode节点,在删除第一个数据时使用;
        boolean flag = true;//一个标记,在找到数据后取反,主要是用于在没有找到对应数据时跳出循环

        //该while循环一旦跳出,则证明finalNode指针已指向最后一个数据
        while (true) {
            if (!(finalNode.nextNode.equals(firstNode))) {
                finalNode = finalNode.nextNode;
            } else {//注意有else和没有else的区别
                break;
            }
        }


        while (true) {

            if (initialNode.nextNode.data.number == number) {//这个if主要用于删除第一个数据,第一个数据比较特殊,需要更改头节点的连接

                finalNode.nextNode = firstNode.nextNode;//最后一个节点的next指向首个数据(也就是待删除数据)的下一个节点
                initialNode.nextNode = firstNode.nextNode;//头节点的next需要指向新的firstNode
                return;

            } else {//如果要删除的数据不在第一个,则使用如下方式,注意,删除数据时temp指针必须在要指向待删除节点的上个节点,所以,
                // 由于第一个节点已经有上面的方法删除了,这里就没必要一开始让它指向头节点了

                while (flag) {
                    if (temp.nextNode.equals(firstNode)) {
                        break;//主要用于没找到时跳出while循环
                    }
                    if (temp.nextNode.data.number == number) {

                        flag = !flag;//找到则取反
                        break;
                    } else {
                        temp = temp.nextNode;//没找到则指针后移
                    }
                }//这个子while循环结束则意味着temp指针已经指向待删除数据的上一个节点了


                if (flag) {
                    System.out.println("No data with value equal to " + number + " was found!");//flag为true则表示不存在这个数据,结束即可
                    return;
                } else {
                    temp.nextNode = temp.nextNode.nextNode;//temp指针指向下一个节点(也即是待删除结点)的下一个
                    return;
                }

            }
        }

    }

    public void updateDate(int oldNumber, int newNumber) {
        Node temp = initialNode.nextNode;
        Node firstNode = initialNode.nextNode;
        boolean flag = true;
        while (true) {
            if (temp.nextNode.equals(firstNode) && temp.data.number != oldNumber) {
                //这里要特别注意,不能仅仅以temp的下一个元素等于first就判断,这样的话有bug
                //这个bug就是:当要修改的元素刚好在最后一个时,temp指针也是在最后的,此时应该修改完数据再break,而不是直接break
                break;
            }
            if (temp.data.number == oldNumber) {
                flag = !flag;
                break;
            } else {
                temp = temp.nextNode;
            }

        }
        if (flag) {
            System.out.println("No data with value equal to " + oldNumber + " was found!");//flag为true则表示不存在这个数据,结束即可

        } else {
            temp.data.number = newNumber;
        }
    }

    public void searchValue(int value) {
        Node temp = initialNode.nextNode;
        Node firstNode = initialNode.nextNode;
        boolean flag = true;
        while (true) {
            if (temp.nextNode.equals(firstNode)) {
                if (temp.data.number == value) {
                    System.out.println(temp);
                    break;
                } else {
                    flag = !flag;
                    break;
                }
            } else {
                if (temp.data.number == value) {
                    System.out.println(temp);
                    break;
                } else {
                    temp = temp.nextNode;
                }
            }
        }
        if (!flag) {
            System.out.println("No data with value equal to " + value + " was found!");//flag为true则表示不存在这个数据,结束即可

        }
    }
}

4. 测试与调试(自行编写代码测试)

package 环形链表;

import org.junit.Test;

/**
 * @Classname Demo
 * @Description TODO
 * @Date 2022/5/8 16:08
 * @Created by jiawe
 */
public class Demo {
    public static void main(String[] args) {
        CircularLinkedList circularLinkedList = new CircularLinkedList();
        NodeData nodeData1 = new NodeData(1);
        NodeData nodeData2 = new NodeData(2);
        NodeData nodeData3 = new NodeData(3);
        NodeData nodeData4 = new NodeData(4);
        NodeData nodeData5 = new NodeData(5);
        NodeData nodeData6 = new NodeData(5);

//        NodeData nodeData3 = new NodeData(13);

        circularLinkedList.addNode(nodeData1);
        circularLinkedList.addNode(nodeData2);
        circularLinkedList.addNode(nodeData3);
        circularLinkedList.addNode(nodeData4);
        circularLinkedList.addNode(nodeData5);
//        circularLinkedList.dropNode(5);
//        circularLinkedList.dropNode(2);
//        circularLinkedList.updateDate(9, 100);
        System.out.println(circularLinkedList.getCount());
//        circularLinkedList.listAll();
//        circularLinkedList.searchValue(4);
        circularLinkedList.searchValue(1);
        circularLinkedList.searchValue(3);
        circularLinkedList.searchValue(5);
        circularLinkedList.searchValue(9);




    }
//    @Test
//    public void test1(){
//
//        CircularLinkedList circularLinkedList = new CircularLinkedList();
//        System.out.println(circularLinkedList.initialNode.nextNode);
//    }
}

如果发现有Bug,欢迎反馈!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值