java实现数据结构---单链表

java实现数据结构单链表

import java.util.Iterator;
import java.util.Objects;

public class LinkList<T> implements Iterable<T> {//实现Iterable接口,重写iterator方法
    //记录首结点
    private Node1<T> head;
    //记录链表的长度
    private int N;

    public LinkList() {
        //初始化数据
        this.head = new Node1(null, null);
        this.N = 0;
    }

    //获取第一个元素节点,也就是头结点的下一个节点
    public Node1<T> getNode() {
        return head.next;
    }

    //:判断线性表是否为空,是返回true,否返回false
    public boolean isEmpty() {
        return N == 0;
    }

    //获取线性表中元素的个数
    public int length() {
        return N;
    }

    //空置线性表
    public void clear() {
        head.item = null;
        head.next = null;
        N = 0;
    }

    //读取并返回线性表中的第i个元素的值
    public T getItem(int i) {
        if (i < 0 || i >= N) {
            throw new RuntimeException("元素位置非法!");
        }
        Node1<T> n = head.next;
        for (int index = 0; index < i; index++) {
            n = n.next;
        }
        return n.item;
    }

    //往线性表中添加一个元素
    public void add(T t) {
        Node1<T> node = head;
        for (int i = 0; node.next != null; i++) {
            //找到线性表的最后一个节点后停止
            node = node.next;
        }
        //新建一个节点
        Node1<T> newNode = new Node1<>(t, null);
        //将新节点添加到当前链表的最后一个节点的next指针域
        node.next = newNode;
        //长度加一
        N++;
    }

    //在线性表的第i个元素之前插入一个值为t的数据元素
    public void insert(int i, T t) {
        if (i < 0 || i >= N) {
            throw new RuntimeException("插入位置非法");
        }
        //找到i前面的节点,
        Node1<T> NodePrev = head;
        for (int index = 0; index < i; index++) {
            //结束的nodeHead节点就是要插入的i节点前面的一个节点
            NodePrev = NodePrev.next;
        }
        // 找到i节点,
        Node1 curr = NodePrev.next;
        //构建新的节点,并让该新节点的next指向i节点
        Node1<T> newNode = new Node1<>(t, curr);
        //让i之前的节点指向新节点
        NodePrev.next = newNode;
        //长度加一
        N++;
    }

    //删除并返回线性表中第i个数据元素
    public T remove(int i) {
        if (i < 0 || i >= N) {
            throw new RuntimeException("位置不合法");
        }
        //获取头结点
        Node1<T> prev = head;
        //找到i节点的前一个节点
        for (int index = 0; index < i; index++) {
            prev = prev.next;
        }
        //获取i节点
        Node1<T> curr = prev.next;
        //删除i节点,让i节点的前一个节点指向i节点的下一个节点
        prev.next = curr.next;
        //长度减一
        N--;
        return curr.item;
    }

    //返回线性表中首次出现的指定的数据元素的位序号,若不存在,则返回-1。
    public int indexOf(T t) {
        //找到头结点
        Node1<T> prev = head;
        //遍历链表,找t元素
        for (int i = 0; prev.next != null; i++) {
            prev = prev.next;
            if (prev.item.equals(t)) {
                return i;
            }
        }
        //没有找到返回-1
        return -1;
    }

    @Override
    public Iterator<T> iterator() {
        return new TIterator();
    }

    private class TIterator<T> implements Iterator<T> {
        private Node1<T> node;

        public TIterator() {
            this.node = (Node1<T>) head;
        }

        @Override
        public boolean hasNext() {
            return node.next != null;
        }

        @Override
        public T next() {
            node = node.next;
            return node.item;
        }
    }

    //链表的反转

    /**
     * 采用递归的方式,时间复杂度O(n),空间复杂度O(n)
     */
    public void reverse() {
        if (isEmpty()) {
            return;
        }
        reverse(head.next);
    }

    /**
     * @param curr 当前遍历的节点
     * @return 反转后 ,头结点应该指向原链表的最后一个元素
     */
    public Node1<T> reverse(Node1<T> curr) {
        //到了最后一个元素
        if (curr.next == null) {
            //反转后,头结点应该指向原链表中的最后一个元素
            head.next = curr;
            return curr;
        }
        //递归返回的当前节点的下一个节点,就是链表反转后当前节点的上一个节点
        Node1<T> prev = reverse(curr.next);
        prev.next = curr;
        //当前结点的下一个结点设为null
        curr.next = null;
        //返回当前结点
        return curr;
    }

    /**
     * 利用快慢指针求链表的中间值
     * 快指针的速度是慢指针的两倍
     *
     * @param first 传递第一个元素节点,也就是头结点的下一个节点
     * @return 返回链表的中间值
     */
    public T getMiddle(Node1<T> first) {
        //定义慢指针
        Node1<T> slow = first;
        //定义快指针
        Node1<T> fast = first;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow.item;
    }

    /**
     * 快慢指针判断链表中是否有环
     *
     * @param first 第一个元素节点,也就是首元结点
     * @return true表示有环,反之无环
     */
    public boolean isCircle(Node1<T> first) {
        //定义快慢指针
        Node1<T> fast = first;
        Node1<T> slow = first;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast.equals(slow)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        LinkList<?> linkList = (LinkList<?>) o;
        return N == linkList.N &&
                Objects.equals(head, linkList.head);
    }

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

尤雨东

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

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

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

打赏作者

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

抵扣说明:

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

余额充值