Java 手写单链表

Java 手写单向链表

SingleLinkedList.java

package com.muxiaofei.veryday.entity;

/**
 * 单链表
 * @param <T>
 */
public class SingleLinkedList<T> {

    //链表大小
    public int size;
    // 头节点(先初始化一下)
    public Node<T> head = new Node<>();
    // 尾巴节点 (刚开始指向头节点)
    public Node<T> rear = head;

    //数据节点类
    private class Node<T>{
        //data 存储数据
        T data;
        //存储下一个节点的引用指针
        Node<T> next;

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

        public Node() {
        }

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

    /**
     * 从尾部添加数据
     * @param data
     */
    public void addRear(T data){
        // 根据添加的内容 创建一个节点,next域为null
        Node<T> newNode = new Node<>(data);
        // 尾节点的next指向新节点
        rear.next = newNode;
        // 将新节点设置为尾巴节点
        rear = newNode;
        // 链表大小+1
        ++size;
    }

    /**
     * 从头部添加数据
     * @param data
     */
    public void addHead(T data){
        // 根据添加的内容 创建一个节点,next域为null
        Node<T> newNode = new Node<>(data);
        // 新节点的next指向头节点
        newNode.next = head.next;
        // 将新节点设置为头部节点
        head.next = newNode;
        // 链表大小+1
        ++size;
    }

    /**
     * 指定位置添加数据
     * @param date 新节点的数据
     * @param index 插入的位置
     */
    public void insert(T date, int index){
        // 判断边界 看看是否越界
        if (isValid(index)){
            System.out.println("下标超出链表大小");
            return;
        }
        // 获取上一个节点
        Node temp = getBefore(index);
        // 根据添加的内容 创建一个节点,next域为null
        Node<T> newNode = new Node<>(date);
        // 准备插入节点
        // 新节点获取上一个节点指向下一个节点的数据
        newNode.next = temp.next;
        // 上一个节点指向新节点
        temp.next = newNode;
        // 链表长度+1
        ++size;
    }

    /**
     * 删除指定位置节点
     * @param index 指定位置节点
     */
    public void delete(int index){
        // 判断边界 看看是否越界
        if (isValid(index)){
            System.out.println("下标超出链表大小");
            return;
        }
        // 获取上一个节点
        Node temp = getBefore(index);
        // 获取删除位置的下一个节点的坐标
        temp.next = temp.next.next;
        // 如果删除的是最后的节点
        if (index == size){
            // 将倒数第二个节点设置为尾节点
            rear = temp;
        }
        // 链表-1
        --size;
    }

    /**
     * 修改办法
     * @param date 数据类型
     * @param index 修改指定内容
     */
    public void update(T date, int index){
        // 判断边界 看看是否越界
        if (isValid(index)){
            System.out.println("下标超出链表大小");
            return;
        }
        // 获取当前节点
        Node temp = getCurrent(index);
        // 修改
        temp.data = date;
    }

    /**
     * 遍历节点
     */
    public void showList(){
        // 判断边界
        if (size == 0){
            System.out.println("链表长度为0");
            return;
        }
        // head不能动,因此这里要添加一个临时指针
        Node temp = head;
        while (true){
            if (temp == null){
                break;
            }
            System.out.println(temp);
            // 这里很重要,临时节点向后移
            temp = temp.next;
        }

    }

    /**
     * 根据下表获取节点数据
     * @param index
     * @return
     */
    public Object get(int index){
        // 判断边界 看看是否越界
        if (isValid(index)){
            System.out.println("下标超出链表大小");
            return null;
        }
        // 获取当前节点的数据
        return getCurrent(index).data;
    }

    /**
     * 反转链表
     */
    public void reverse(){
        // 判断边界
        if (size == 0){
            System.out.println("链表长度为0");
            return;
        }
        Node temp = this.head.next;
        SingleLinkedList newList = new SingleLinkedList();
        while (true){
            if (temp == null){
                break;
            }
            // 将当前节点利用 头插法 添加到临时链表中 (头插法是关键)
            newList.addHead(temp);
            // 遍历所有的节点
            temp = temp.next;
        }
        // 最后把临时链表的head索引复制给当前链表的head
        this.head = newList.head;
    }

    /**
     * 判断下标是否有效
     * @param index
     * @return
     */
    public boolean isValid(int index){
        if (index > size  || index < 0){
            return true;
        }
        return false;
    }

    /**
     * 获取前面一个的节点
     * @param index
     * @return
     */
    public Node<T> getBefore(int index){
        // 获取头部节点
        Node temp = head;
        // 找到删除位置的前一个节点,因此是index-1 因为这是单向链表 不能指向前一个节点
        for (int i = 1; i <= index - 1; i++) {
            temp = temp.next;
        }
        return temp;
    }

    /**
     * 获取当前节点
     * @param index
     * @return
     */
    public Node<T> getCurrent(int index){
        // 获取头部节点
        Node temp = head;
        // 找到删除位置的前一个节点,因此是index-1 因为这是单向链表 不能指向前一个节点
        for (int i = 1; i <= index; i++) {
            temp = temp.next;
        }
        return temp;
    }
}

测试类

SingleLinkedListDemo1.java

package com.muxiaofei.veryday.demo;

import com.muxiaofei.veryday.entity.SingleLinkedList;

/**
 *  测试单向链表
 */
public class SingleLinkedListDemo1 {
    public static void main(String[] args) {
        SingleLinkedList<String> myList = new SingleLinkedList<>();
        myList.addRear("字节跳动");
        myList.addRear("阿里");
        myList.addRear("腾讯");
        myList.addRear("美团");
        myList.showList();
        System.out.println("链表的大小:" + myList.size);

        myList.insert("华为", 4);
        myList.showList();
        System.out.println("链表的大小:" + myList.size);

        myList.update("百度", 5);
        myList.showList();
        System.out.println("链表的大小:" + myList.size);

        myList.delete(3);
        myList.showList();
        System.out.println("链表的大小:" + myList.size);

        System.out.println(myList.get(1));

        myList.addHead("上官婉儿");
        myList.addHead("橘右京");
        myList.addHead("廉颇");
        myList.showList();
        System.out.println("链表的大小:" + myList.size);
    }
}

测试类2

SingleLinkedListDemo2.java

package com.muxiaofei.veryday.demo;

import com.muxiaofei.veryday.entity.SingleLinkedList;

/**
 * 反转链表
 */
public class SingleLinkedListDemo2 {
    public static void main(String[] args) {
        SingleLinkedList myList = new SingleLinkedList();
        myList.addRear("华为");
        myList.addRear("字节跳动");
        myList.addRear("百度");
        myList.addRear("腾讯");
        myList.showList();
        // 反转
        myList.reverse();
        myList.showList();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值