Java练习:构造简单的单链表

目标构造简单的单链表

实现功能如下

  1. 插入数据
  2. 查询数据
  3. 移除数据
  4. 获取Size
  5. 反转数据
  6. 遍历数据
代码:
package com.miracle.study.list;

import org.junit.jupiter.api.Test;

import java.util.Iterator;
import java.util.function.Predicate;

/**
 * @author Miracle
 * @date 2021/4/7 16:34
 */
public class TList<T> implements Iterable<T> {

    /**
     * 头部节点
     */
    private Node<T> head = null;

    /**
     * 数据量
     */
    private int size = 0;

    /**
     * 节点
     * @param <T>
     */
    static class Node<T>{

        /**
         * 存储数据
         */
        private T data;

        /**
         * 下一个节点位置
         */
        private Node<T> next = null;

        public Node(T data){
            this.data = data;
        }

        public T get(){
            return data;
        }
    }

    /**
     * 遍历
     * @return
     */
    @Override
    public Iterator<T> iterator() {

        return new Iterator<T>() {

            int cursor = 0;

            @Override
            public boolean hasNext() {
                return cursor != size;
            }

            @Override
            public T next() {
                var node = head;
                for (int i = 0; i < cursor; i++){
                    node = node.next;
                }
                cursor++;
                return node.get();
            }
        };
    }

    /**
     * 头插法
     * @param data 数据
     */
    public void insert(T data){
        var node = new Node<>(data);
        // 新节点指针指向当前头节点
        node.next = head;
        // 修改头节点指向当前节点
        head = node;
        // 数据量+1
        size++;
    }

    /**
     * 递归尾插法
     * @param node
     * @param data
     * @return
     */
    private Node<T> tailInsert(Node<T> node, T data){
        if (node != null){
             node.next = tailInsert(node.next, data);
        }else {
            node = new Node<>(data);
        }
        return node;
    }

    public void tailInsert(T data){
        this.head = tailInsert(head, data);
        size++;
    }

    /**
     * 查找数据
     * @param predicate
     * @return
     */
    public Node<T> find(Predicate<T> predicate){
        if (head == null){
            return null;
        }

        if (predicate.test(head.get())){
            return head;
        }
        var node = head;
        while (node.next != null){
            node = node.next;
            if (predicate.test(node.get())){
                return node;
            }
        }
        return null;
    }

    /**
     * 移除
     * @param node
     */
    public void remove(Node<T> node){
        // 判断节点是否为空
        if (node == null){
            return;
        }
        // 判断节点是否为头部直接返回
        if (node == head){
            head = head.next;
        }
        var p = head;
        var pn = head.next;
        while (pn != null){
            // 判断是否是要删除的节点
            if (pn == node){
                // 将指向要删除的节点的指针指向其后一个节点
                p.next = pn.next;
                // 数据量 -1
                size --;
            }
            // 移动到下一个位置继续判断
            p = pn;
            pn = pn.next;
        }
    }

    /**
     * 获取数据数量,遍历获取
     * @return
     */
    public int Size(){
        int size = 0;
        var p = head;

        while (p != null){
            p = p.next;
            size++;
        }
        return size;
    }

    /**
     * 获取数据数量,直接获取,需要在插入和移除操作中做数据修改
     * @return
     */
    public int getSize(){
        return this.size;
    }

    /**
     * 反转
     */
    public void reverse(){
        // 前一个节点指针
        Node<T> prev = null;
        // 当前节点指针
        var current = head;
        // 后一个节点指针
        Node<T> next = null;

        while (current != null){
            // 记录下一个节点
            next = current.next;
            // 改变当前节点的链路方向
            current.next = prev;
            // 记录当前节点
            prev = current;
            // 移动节点
            current = next;
        }
        head = prev;
    }

    /**
     * 迭代反转
     * @param node
     * @return
     */
    private Node<T> iteReverse(Node<T> node){
        // 主要用于判断是否是最后一个节点,它被反转成为头部要返回去。
        if (node == null || node.next == null){
            return node;
        }
        // 获取最后一个节点(反转后的头节点)
        var result = iteReverse(node.next);
        // 将后一个节点的指针指向当前节点
        node.next.next = node;
        // 去除当前节点的指针指向
        node.next = null;
        // 返回头部节点回去
        return result;
    }

    public void iteReverse(){
        head = iteReverse(head);
    }

    @Override
    public String toString(){
        var node = head;
        StringBuilder stringBuilder = new StringBuilder();
        var i = 0;
        while (node != null){
            stringBuilder.append(i + ":" + node.get() + " ");
            node = node.next;
            i++;
        }
        return stringBuilder.toString();
    }


    @Test
    public void test(){
        TList<Integer> tList = new TList<>();
        // 头部插入
        tList.insert(1);
        tList.insert(2);
        // 尾部插入
        tList.tailInsert(3);
        tList.tailInsert(4);
        // 查找
        var node3 = tList.find(a -> a == 3);
        // 移除
        tList.remove(node3);
        // 三指针反转
        tList.reverse();
        // 迭代反转
        tList.iteReverse();
        // 遍历
        for (var i : tList){
            System.out.println(i);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

萌白在努力

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

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

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

打赏作者

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

抵扣说明:

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

余额充值