Java 自己实现一个单链表

      链表的数据结构在平时开发中很经常用到,为了更了解,自己实现了一个单链表。

  • 链表:
    Java 自己实现一个单链表_第1张图片

  • 添加节点:找到要添加的位置所在结点的前一个结点为x,下一个为y,断开 x -> y,增加 x -> new_node,new_node -> y
    Java 自己实现一个单链表_第2张图片

  • 删除结点:找到删除的结点old,old前一个结点x,old后一个结点y,断开x -> old,改为x -> y的连接
    Java 自己实现一个单链表_第3张图片
    虽然网上有很多人写过Java实现的单链表,但还是建议自己写一遍,这样才能加深印象,更了解其中的原理。就我而言,写的过程中没有注意到的点如下:

  1. Java没有结构体Struct这个数据结构,所以只能写一个类MyNode来代替链表中的一个结点。里面定义了数据域data变量,和一个指向下一个节点的自身对象next;
  2. 在打印结点元素、添加结点时,涉及到头结点移动,代码中引入了MyNode的tmp对象,因为一旦移动了head指向的结点,就是永久改变了;
  3. 代码中63行左右,head.next 和 cur 指向问题,两行的顺序不能调换;
  4. 写完代码后,发现可以改进一下,把MyLinked改为泛型的,而不是指定了(原先是int)某个类型.

代码如下:

/**
 * @ClassName MyLinked
 * @Description TODO 自己实现链表 , 需要实现的方法:
 *                         addHead(val) 添加头结点
 *                         add(val) 在末尾添加结点
 *                         add(post,val) 在位置post添加一个节点val
 *                         printAllNode() 打印所有结点
 *                         size()    统计链表的长度
 *                         remove()   删除末尾结点
 *                         remove(post) 删除在第post个位置的结点
 *                         removeHead() 删除头结点
 * @Author ylqdh
 * @Date 2020/4/10 9:26
 */
class MyNode<E> {
    E data;
    MyNode<E> next = null;

    MyNode (E data) {
        this.data = data;
    }
}
public class MyLinked<E> {
    MyNode<E> head = null;

    // 初始化,在头结点的前面人为的添加了一个head,数据为0,下一个节点为null
    MyLinked () {
        head = new MyNode(0);
        head.next = null;
    }

    /**
     * 添加节点,末尾添加
     * @param e 要添加的值
     * @return
     */
    public boolean add (E e) {
        MyNode<E> tmp = head;
        MyNode<E> cur = new MyNode(e);
        while (tmp.next != null) {
            tmp = tmp.next;
        }

        tmp.next = cur;

        return true;
    }

    /**
     *  添加节点,添加在头结点
     * @param e  要添加的值
     * @return
     */
    public boolean addHead (E e) {
        MyNode<E> cur = new MyNode(e);

        cur.next = head.next;  // 注意这一行和下一行不能调换
        head.next = cur;
        return true;
    }

    /**
     *  添加结点,在中间某个位置添加
     * @param post  添加的位置,从1开始计数
     * @param e     添加的值
     * @return
     */
    public boolean add (int post, E e) {
        // 位置不能小于0
        if (post < 0 | post > size()) {
            return false;
        }
        MyNode<E> cur = new MyNode(e);
        MyNode<E> tmp = head;
        int i = 0;
        while (i < post-1) {
            tmp = tmp.next;
            i++;
        }

        cur.next = tmp.next;
        tmp.next = cur;

        return true;
    }

    // 打印所有结点的值
    public void printAllNode () {
        MyNode<E> tmp = head;
        while (tmp.next != null) {
            System.out.print(tmp.next.data+" --> ");  // 注意这里是打印tmp.next的值
            tmp = tmp.next;
        }
        System.out.println(" null");
    }

    // 统计结点的个数
    public int size() {
        int sum = 0;
        MyNode<E> tmp = head;
        while (tmp.next != null) {
            sum++;
            tmp = tmp.next;
        }
        return sum;
    }

    // 删除,删除头结点
    public boolean removeHead() {
        head.next = head.next.next;
        return true;
    }

    /**
     *   删除,删除指定位置的结点
     * @param post 要删除的位置
     * @return
     */
    public boolean remove(int post) {
        if (post < 0 || post > size()) {
            System.out.println("删除的位置小于0或者大于链表的长度,删除操作不执行");
            return false;
        }
        int i = 0;
        MyNode<E> tmp = head;
        while (i < post-1) {
            tmp = tmp.next;
            i++;
        }
        tmp.next = tmp.next.next;
        return true;
    }

    /**
     *  删除,不加参数,就是删除末尾的结点
     * @return
     */
    public boolean remove() {
        if (head.next == null) {
            return false;
        }
        int i = 0;
        MyNode<E> tmp = head;
        while (i < size()-1) {
            tmp = tmp.next;
            i++;
        }
        tmp.next = null;
        return true;
    }
}

测试代码:

public class Main {
    public static void main(String[] args) {

        MyLinked<Integer> myLinked = new MyLinked();

        myLinked.add(1);

        myLinked.printAllNode();

        myLinked.add(2);
        myLinked.add(3);
        myLinked.add(2,4);
        myLinked.addHead(5);

        myLinked.printAllNode();
        System.out.println("此时的长度: "+myLinked.size()+"\t");

        myLinked.removeHead();
        myLinked.remove(2);
        myLinked.printAllNode();

    }
}

参考自小仙女的博客: https://blog.csdn.net/qq_37937537/article/details/80101744

你可能感兴趣的:(练习题)