java 实现带头节点的循环单链表

学一学循环链表

描述

将单链表的尾端节点指针域的指向由null指向首节点即可

结构图

空链表

非空链表

在这里插入图片描述

循环截至条件

节点的指针域是否指向首节点

JAVA代码实现

package com.example.demo.data;

import java.util.Objects;

/**
 * @author tm
 * @date 2021-06-25 14:49
 * @description java 实现带头节点的循环单链表
 */
public class CycleSingleLinkList<T> {


    public static void main(String[] args) {
        CycleSingleLinkList<Object> objectCycleSingleLinkList = new CycleSingleLinkList<>();
        System.out.println("===========选择头插法(默认尾插法)============");
        objectCycleSingleLinkList.headInsert = false;
        System.out.println("===========新增============");
        for (int i = 0; i < 10; i++) {
            objectCycleSingleLinkList.add(i);
        }
        System.out.println("新增完后长度为:" + objectCycleSingleLinkList.size + " 元素情况:" + objectCycleSingleLinkList.toString());
        objectCycleSingleLinkList.add(0, new Integer("1000"));
        System.out.println("0标增加数据为1000的节点后长度为:" + objectCycleSingleLinkList.size + " 元素情况:" + objectCycleSingleLinkList.toString());

        System.out.println("===========删除============");
        Boolean remove = objectCycleSingleLinkList.remove(1);
        System.out.println("删除第1个节点" + remove + "之后长度为:" + objectCycleSingleLinkList.size + " 元素情况:" + objectCycleSingleLinkList.toString());
        Boolean remove1 = objectCycleSingleLinkList.remove(new Integer("9"));
        System.out.println("删除数据为9节点" + remove1 + "之后长度为:" + objectCycleSingleLinkList.size + " 元素情况:" + objectCycleSingleLinkList.toString());
        System.out.println("===========查询============");
        System.out.println("通过数据1000查询" + objectCycleSingleLinkList.get(new Integer("1000")).data);
        System.out.println("通过下标0查询" + objectCycleSingleLinkList.get(0).data);

        System.out.println("===========修改============");
        boolean replace = objectCycleSingleLinkList.replace(0, new Integer(10000));
        System.out.println("替换0下标数据为1w:" + replace + "之后长度为:" + objectCycleSingleLinkList.size + " 元素情况:" + objectCycleSingleLinkList.toString());
        objectCycleSingleLinkList.replace(new Integer(8), new Integer(800));
        System.out.println("替换据8为800:" + "之后长度为:" + objectCycleSingleLinkList.size + " 元素情况:" + objectCycleSingleLinkList.toString());

    }


    //特定位置替换数据
    private boolean replace(int index, T data) {
        //检查index 范围
        checkPositionIndex(index);
        //确定头插 尾插
        int currentIndex = getBorder(index);
        //获取具体下标的数据
        Node<T> current = getPositionPreNode(currentIndex + 1);
        current.data = data;
        return true;
    }

    //替换老数据
    private T replace(T oldData, T newData) {
        //获取具体下标的数据
        Node<T> current = get(oldData);
        if (null != current) {
            current.data = newData;
            return oldData;
        }
        return null;
    }

    private Node<T> get(int index) {
        //范围
        checkPositionIndex(index);
        //确定头插 尾插
        int border = getBorder(index);
        //头节点不存在数据 所以从第一个有数据节点开始
        Node<T> node = this.head.next;
        for (int i = 0; i < border; i++) {
            node = node.next;
        }
        return node;
    }

    private Node<T> get(T oldData) {
        //头节点不存在数据 所以从第一个有数据节点开始
        Node<T> node = this.head.next;
        while (node != this.head) {
            if (Objects.equals(node.data, oldData)) {
                return node;
            }
            node = node.next;
        }
        return null;
    }


    //删除特定数据的节点
    private Boolean remove(T data) {
        Node<T> current = get(data);
        if (null == current) {
            return true;
        }
        Node<T> next = current.next;
        //小优化 针对尾节点O(n)和非尾节点O(1)删除
        if (next != this.head) {
            //非尾节点O(1)删除
            //将下一个节点的向下引用、数据赋予给当前节点
            current.data = next.data;
            current.next = next.next;
            //help Gc
            next.next = null;
            next.data = null;
        } else {
            //尾节点O(n)删除
            Node<T> node = this.head;
            while (node.next != current) {
                node = node.next;
            }
            node.next = this.head;
            //help Gc
            current.next = null;
            current.data = null;
        }
        this.size--;
        return true;
    }

    //删除插入的第x  从0开始
    private Boolean remove(int index) {
        //检查index 范围
        checkPositionIndex(index);
        //确定是尾插法还是头插法
        int border = getBorder(index);
        Node<T> pre = getPositionPreNode(border);
        Node<T> del = pre.next;
        pre.next = del.next;
        //help Gc
        del.next = null;
        del.data = null;
        this.size--;
        return true;
    }

    //确定是尾插法还是头插法
    private int getBorder(int index) {
        int border;
        if (this.headInsert) {
            //1.头插法(index顺序就是反的)
            border = size - index - 1;
        } else {
            //2.尾插法(index)
            border = index;
        }
        return border;
    }

    private Node<T> getPositionPreNode(int index) {
        Node<T> pre = this.head;
        for (int i = 0; i < index; i++) {
            pre = pre.next;
        }
        return pre;
    }

    //特定位置插入数据节点
    private void add(int index, T data) {
        //检查index 范围
        checkPositionIndex(index);
        int border = getBorder(index);
        //获取具体下标的数据
        Node<T> pre = getPositionPreNode(border);
        pre.next = new Node<T>(data, pre.next);
        this.size++;
    }

    //顺序插入数据节点
    private void add(T t) {
        //头插法
        if (this.headInsert) {
            Node<T> head = this.head;
            head.next = new Node<>(t, head.next);
        } else {
            //尾插法
            Node<T> last = this.head;
            while (last.next != this.head) {
                last = last.next;
            }
            last.next = new Node<>(t, this.head);
        }
        this.size++;
    }


    //检查下表范围
    private void checkPositionIndex(int index) {
        if (!isPositionIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private boolean isPositionIndex(int index) {
        return index >= 0 && index <= size - 1;
    }

    private String outOfBoundsMsg(int index) {
        return "Index: " + index + ", size: " + (size - 1);
    }

    @Override
    public String toString() {
        //头节点不存在数据 所以从第一个有数据节点开始
        Node<T> node = this.head.next;
        StringBuilder stringBuilder = new StringBuilder();
        while (node != this.head) {
            stringBuilder.append(node.data);
            stringBuilder.append(" ");
            node = node.next;
        }

        return stringBuilder.toString();
    }

    //采用头插法还是尾插法
    private boolean headInsert;

    //线性表长度
    private int size;

    //头节点
    private Node<T> head;


    public CycleSingleLinkList() {
        this.head = new Node<>(null, null);
        this.head.next = this.head;
    }

    //定义节点
    private static class Node<T> {
        //节点数据
        private T data;
        //后驱引用
        private Node<T> next;

        public Node(T data, Node<T> next) {
            this.data = data;
            this.next = next;
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值