【Java】/* 单向链表 - 底层实现 */

【难点】:remove、removeAllKey

一、IList

package bagfour;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: tangyuxiu
 * Date: 2024-08-20
 * Time: 20:58
 */
public interface IList {
    //头插法
    void addFirst(E data);
    //尾插法
    void addLast(E data);
    //任意位置插入,第一个数据节点为0号下标
    void addIndex(int pos,E data);
    //查找是否包含关键字key是否在单链表当中
    boolean contains(E key);
    //删除第一次出现关键字为key的节点
    void remove(E key);
    //删除所有值为key的节点
    void removeAllKey(E key);
    //得到单链表的长度
    int size();
    void clear();
    void display();
}

二、MyLinkedList

package bagfour;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: tangyuxiu
 * Date: 2024-08-20
 * Time: 20:58
 */
public class MyLinkedList implements IList {
    /* 使用内部类来定义链表节点 */
    private static class ListNode {
        E val;
        ListNode next;//默认为null

        public ListNode(E val) {
            this.val = val;
        }
    }

    private ListNode head;

    /* 头插 */
    @Override
    public void addFirst(E data) {
        ListNode newNode = new ListNode<>(data);
        this.head.next = this.head;
        this.head = newNode;
    }

    /* 尾插 */
    @Override
    public void addLast(E data) {
        ListNode newNode = new ListNode<>(data);
        //1. 如果链表为null
        if (this.head == null) {
            this.head = newNode;
            return;
        }
        //2. 尾插
        ListNode cur = this.head;
        while (cur.next != null) {
            cur = cur.next;
        }
        cur.next = newNode;
    }

    /* 判断add位置是否合法 */
    private boolean addIndexIsLegal(int pos) {
        if (pos < 0 || pos > this.size()) {
            return false;
        }
        return true;//如果链表为null,且pos位置为0,此时也是合法的
    }

    /* 任意位置插入 */
    @Override
    public void addIndex(int pos, E data) {
        //1. 判断add位置是否合法
        if (!this.addIndexIsLegal(pos)) {
            return;
        }
        //2. pos == 0(链表为null且index=0,也走的这里)
        if (pos == 0) {
            this.addFirst(data);
            return;
        }
        //3. pos == size()
        if (pos == this.size()) {
            this.addLast(data);
            return;
        }
        //4. 其他位置
        ListNode newNode = new ListNode<>(data);
        ListNode cur = this.head;
        //寻找pos节点的前一个节点
        //【思路】本来想要找到到index下标所指向的节点的,但发现
        // 我们要找的其实不是index下标所指向的节点而是要找到它的前一个节点
        // 那么我们将cur原本要走的index步,改为走index - 1步即可
        for (int i = 0; i < pos - 1; i++) {//这里的问题头插部分已经考虑到了
            cur = cur.next;
        }
        newNode.next = cur.next;
        cur.next = newNode;
    }

    /* 是否存在某元素 */
    @Override
    public boolean contains(E key) {
        ListNode cur = this.head;
        while (cur != null) {
            if (cur.val.equals(key)) {
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

    /* 删除第一次出现关键字为key的节点 */
    @Override
    public void remove(E key) {
        //1. 如果链表为null
        if (this.head == null) {
            return;
        }
        //2. 如果key在头节点处
        if (this.head.val.equals(key)) {
            this.head = this.head.next;
            return;
        }
        //3. 如果key在其他位置
        ListNode pre = this.head;
        //找到key的前一个节点
        while (pre.next != null) {
            ListNode del = pre.next;
            if (del.val.equals(key)) {
                pre.next = del.next;
                return;
            }
            pre = pre.next;
        }
    }

    /* 删除所有值为key的节点 */
    @Override
    public void removeAllKey(E key) {
        //1. 如果链表为null
        if (this.head == null) {
            return;
        }
        //2. 其他位置
        ListNode pre = this.head;
        ListNode del = pre.next;
        while (pre.next != null) {
            if (del.val.equals(key)) {
                pre.next = del.next;
                //del = del.next;
            } else {
                pre = pre.next;
                //del = del.next;
            }
            del = del.next;
        }
        //3. 如果key在头节点处
        if (this.head.val.equals(key)) {
            //为什么下行代码不写成pre = pre.next呢?
            //答:“正常”的代码中pre,find只是工具,真正的head一直仍然指向的是同一个节点
            this.head = this.head.next;
        }
    }

    /* 得到单链表的长度 */
    @Override
    public int size() {
        int count = 0;
        ListNode cur = this.head;
        while (cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

    /* 清空链表 */
    @Override
    public void clear() {
        ListNode cur = this.head;
        while (cur != null) {
            cur.val = null;
            cur = cur.next;
        }
        this.head = null;
    }

    /* 打印 */
    @Override
    public void display() {
        ListNode cur = this.head;
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }
}

你可能感兴趣的:(数据结构,java,数据结构)