Java简单带你手把手实现双链表

1.创建NodeDouble类

class NodeDouble<T> {
    
    
    private T val;//数据域
    private NodeDouble prev;//前驱节点
    private NodeDouble next;//后继节点

    private NodeDouble headNode = null;//头节点
    private NodeDouble tailNode = null;//尾节点

	// 构造方法
    NodeDouble(T val) {
    
    
        this.val = val;
    }
}

2. 头插(addFirst)

    // 头插
    void addFirst(T val) {
    
    
        NodeDouble node = new NodeDouble(val);
        if (this.headNode == null) {
    
    //如果是第一次插入:head和tail都相同
            this.headNode = node;
            this.tailNode = node;
        } else {
    
    
            node.next = this.headNode;//新结点的next存储head
            this.headNode.prev = node;//旧的head结点prev域存储新node头结点的prev
            this.headNode = node;//将node作为新的头结点
        }
    }

    private static void testAddFirst() {
    
    
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 10; i++) {
    
    
            node.addFirst(i);
        }
        node.display();
    }

3. 尾插(addLast)

    // 尾插
    void addLast(T val) {
    
    
        NodeDouble node = new NodeDouble(val);
        if (this.headNode == null) {
    
    
            this.headNode = node;
            this.tailNode = node;
        } else {
    
    
        	/*NodeDouble cur = this.headNode;
            while (cur.next != null) {// 也可以使用单链表的形式找到尾巴再插入
                cur = cur.next;
            }
            cur.next = node;
            node.prev = cur;
            this.tailNode = node;*/
            
            this.tailNode.next = node;//把尾结点tail的next指向新的node结点
            node.prev = this.tailNode;//新的node结点的prev存储旧tail尾结点
            this.tailNode = node;//将node作为新tail结点
        }
    }

    private static void testAddLast() {
    
    
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 10; i++) {
    
    
            node.addLast(i);
        }
        node.display();
    }

4. 任意位置插入(addIntex)

    // 任意位置插入
    void addIndex(int index, T val) {
    
    
        NodeDouble node = new NodeDouble(val);
        if (index == 0) {
    
    
            addLast(val);
        } else if (index == size()) {
    
    
            addLast(val);
        } else if (index > 0 && index < size()) {
    
    
            NodeDouble cur = this.headNode;
            while ((index - 1) != 0) {
    
    
                cur = cur.next;
                --index;
            }
            node.next = cur.next;
            node.prev = cur;
            cur.next = node;
        } else {
    
    
            throw new RuntimeException(index + "越界");
        }
    }

    private static void testIndex() {
    
    
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 10; i++) {
    
    
            node.addIndex(i, i);
        }
        node.display();
    }

5. 删除第一次出现的 val(remove)

    // 删除第一次出现的 val
    void remove(T val) {
    
    
        /*if (this.headNode.val == val) {//使用单链表的形式逐一删除
            this.headNode = this.headNode.next;
            this.headNode.prev = null;
        } else {
            NodeDouble cur = this.headNode;
            while (cur.next != null) {
                if (cur.next.val == val || cur.next.val.equals(val)) {
                    break;
                }
                cur = cur.next;
            }
            NodeDouble del = cur.next;
            cur.next = del.next;
            if (cur.next != null){
                del.next.prev = cur;
            }else{
                this.tailNode = cur.prev;
            }
        }*/
        
        NodeDouble cur = this.headNode;//使用双向链表的特性进行删除操作
        while (cur != null) {
    
    //防止尾结点的cur.next指向空指针异常
            if (cur.val == val || cur.val.equals(val)) {
    
    //找到了指定的 val 值节点
                if (cur == this.headNode) {
    
    //如果是头节点
                	this.headNode = this.headNode.next;//把之前的头结点的移动到头结点下一个结点
                    if (this.headNode == null){
    
    //在判断目前的头节点是否为null
                        this.tailNode = null;// 说明新的头节点也是尾节点
                    }else{
    
    
                        this.headNode.prev = null;//说明新的头节点之后还有节点,把头节点的前驱置为 null
                    }
                } else {
    
    
                    cur.prev.next = cur.next;//先把被删除节点前驱的后继绑定被删除节点的后驱
                    if (cur.next != null){
    
    //在判断被删除的是不是尾结点[当cur.next==null则说明此cur是倒数第二个结点]
                        cur.next.prev = cur.prev;//前后前驱节点绑定
                    }else{
    
    
                        this.tailNode = cur.prev;//删除尾巴结点只需要移动tail
                    }
                }
                break;
            }
            cur = cur.next;
        }
    }

    private static void testRemove() {
    
    
        System.out.println("多个节点:");
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 10; i++) {
    
    
            node.addLast(i);
            node.addLast(5);
        }
        node.display();
        node.remove(5);
        node.display();
        System.out.println("仅有一个节点:");
        node = new NodeDouble(null);
        node.addLast(5);
        node.display();
        node.remove(5);
        node.display();
    }

如图所示删除的是0x300这个节点的示意图
把0x200的next后继指向0x600;把0x600prev前驱指向0x200
在这里插入图片描述

6. 删除所有 val 相等的结点(removeAll)

    // 删除所有 val 相等的结点
    void removeAll(T val){
    
    
        NodeDouble cur = this.headNode;
        while(cur != null){
    
    
            if (cur.val == val || cur.val.equals(val)){
    
    
                // 判断是否需要删除头结点
                if (cur == this.headNode){
    
    
                   	this.headNode = this.headNode.next;
                    if (this.headNode == null){
    
    
                        this.tailNode = null;
                    }else{
    
    
                        this.headNode.prev = null;
                    }
                }else{
    
    
                    cur.prev.next = cur.next;
                    if (cur.next != null){
    
    
                        cur.next.prev = cur.prev;
                    }else{
    
    
                        this.tailNode = cur.prev;
                    }
                }
            }
            cur = cur.next;
        }
    }

    private static void testRemoveAll() {
    
    
        System.out.println("多个节点:");
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 10; i++) {
    
    
            node.addLast(i);
            node.addLast(5);
        }
        node.display();
        node.removeAll(5);
        node.display();
        System.out.println("仅有一个节点:");
        node = new NodeDouble(null);
        node.addLast(5);
        node.display();
        node.removeAll(5);
        node.display();
    }

7. 长度(size)

    // 长度
    private int size() {
    
    
        NodeDouble cur = this.headNode;
        int len = 0;
        while (cur != null) {
    
    
            ++len;
            cur = cur.next;
        }
        return len;
    }

8. 打印(display)

// 打印
    void display() {
    
    
        NodeDouble cur = this.headNode;
        while (cur != null) {
    
    
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }

9. 包含(contains)

    // 包含
    boolean contains(T val) {
    
    
        NodeDouble cur = this.headNode;
        while (cur != null) {
    
    
            if (cur.val == val || cur.val.equals(val)) {
    
    
                return true;
            }
            cur = cur.next;
        }
        return false;
    }
    
    private static void testContains() {
    
    
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 5; i++) {
    
    
            node.addLast(i);
        }
        for (int i = 0; i < 10; i++) {
    
    
            System.out.println(i + ": " + node.contains(i));
        }
    }

10. 清空(clear)

    // 清空
    void clear(){
    
    
        NodeDouble cur = this.headNode;
        while(this.headNode != null){
    
    // 需要手动一个一个的删除后继和前驱
            cur = cur.next;
            this.headNode.prev = null;
            this.headNode.next = null;
            this.headNode = cur;
        }
        this.tailNode = null;
    }
    
    private static void testClear(){
    
    
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 5; i++) {
    
    
            node.addLast(i);
        }
        node.display();
        System.out.println("清空:");
        node.clear();
        node.display();
    }

11. 完整代码

class NodeDouble<T> {
    
    
    private T val;
    private NodeDouble prev;
    private NodeDouble next;

    private NodeDouble headNode = null;
    private NodeDouble tailNode = null;

    NodeDouble(T val) {
    
    
        this.val = val;
    }

    // 头插
    void addFirst(T val) {
    
    
        NodeDouble node = new NodeDouble(val);
        if (this.headNode == null) {
    
    
            this.headNode = node;
            this.tailNode = node;
        } else {
    
    
            node.next = this.headNode;
            this.headNode.prev = node;
            this.headNode = node;
        }
    }

    // 尾插
    void addLast(T val) {
    
    
        NodeDouble node = new NodeDouble(val);
        if (this.headNode == null) {
    
    
            this.headNode = node;
            this.tailNode = node;
        } else {
    
    
            NodeDouble cur = this.headNode;
            while (cur.next != null) {
    
    
                cur = cur.next;
            }
            cur.next = node;
            node.prev = cur;
            this.tailNode = node;
        }
    }

    // 任意位置插入
    void addIndex(int index, T val) {
    
    
        NodeDouble node = new NodeDouble(val);
        if (index == 0) {
    
    
            addLast(val);
        } else if (index == size()) {
    
    
            addLast(val);
        } else if (index > 0 && index < size()) {
    
    
            NodeDouble cur = this.headNode;
            while ((index - 1) != 0) {
    
    
                cur = cur.next;
                --index;
            }
            node.next = cur.next;
            node.prev = cur;
            cur.next = node;
        } else {
    
    
            throw new RuntimeException(index + "越界");
        }
    }

    // 删除第一次出现的 val
    void remove(T val) {
    
    
        /*if (this.headNode.val == val) {
            this.headNode = this.headNode.next;
            this.headNode.prev = null;
        } else {
            NodeDouble cur = this.headNode;
            while (cur.next != null) {
                if (cur.next.val == val || cur.next.val.equals(val)) {
                    break;
                }
                cur = cur.next;
            }
            NodeDouble del = cur.next;
            cur.next = del.next;
            if (cur.next != null){
                del.next.prev = cur;
            }else{
                this.tailNode = cur.prev;
            }
        }*/
        NodeDouble cur = this.headNode;
        while (cur != null) {
    
    
            if (cur.val == val || cur.val.equals(val)) {
    
    
                if (cur == this.headNode) {
    
    
                    this.headNode = this.headNode.next;
                    if (this.headNode == null) {
    
    
                        this.tailNode = null;
                    } else {
    
    
                        this.headNode.prev = null;
                    }
                } else {
    
    
                    cur.prev.next = cur.next;
                    if (cur.next != null) {
    
    
                        cur.next.prev = cur.prev;
                    } else {
    
    
                        this.tailNode = cur.prev;
                    }
                }
                break;
            }
            cur = cur.next;
        }
    }

    // 删除所有 val 相等的结点
    void removeAll(T val) {
    
    
        NodeDouble cur = this.headNode;
        while (cur != null) {
    
    
            if (cur.val == val || cur.val.equals(val)) {
    
    
                // 判断是否需要删除头结点
                if (cur == this.headNode) {
    
    
                    this.headNode = this.headNode.next;
                    if (this.headNode == null) {
    
    
                        this.tailNode = null;
                    } else {
    
    
                        this.headNode.prev = null;
                    }
                } else {
    
    
                    cur.prev.next = cur.next;
                    if (cur.next != null) {
    
    
                        cur.next.prev = cur.prev;
                    } else {
    
    
                        this.tailNode = cur.prev;
                    }
                }
            }
            cur = cur.next;
        }
    }

    // 长度
    private int size() {
    
    
        NodeDouble cur = this.headNode;
        int len = 0;
        while (cur != null) {
    
    
            ++len;
            cur = cur.next;
        }
        return len;
    }

    // 打印
    void display() {
    
    
        NodeDouble cur = this.headNode;
        while (cur != null) {
    
    
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    // 包含
    boolean contains(T val) {
    
    
        NodeDouble cur = this.headNode;
        while (cur != null) {
    
    
            if (cur.val == val || cur.val.equals(val)) {
    
    
                return true;
            }
            cur = cur.next;
        }
        return false;
    }
    // 清空
    void clear(){
    
    
        NodeDouble cur = this.headNode;
        while(this.headNode != null){
    
    
            cur = cur.next;
            this.headNode.prev = null;
            this.headNode.next = null;
            this.headNode = cur;
        }
        this.tailNode = null;
    }
}

public class test {
    
    
    private static void testAddFirst() {
    
    
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 10; i++) {
    
    
            node.addFirst(i);
        }
        node.display();
    }

    private static void testAddLast() {
    
    
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 10; i++) {
    
    
            node.addLast(i);
        }
        node.display();
    }

    private static void testIndex() {
    
    
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 10; i++) {
    
    
            node.addIndex(i, i);
        }
        node.display();
    }

    private static void testRemove() {
    
    
        System.out.println("多个节点:");
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 10; i++) {
    
    
            node.addLast(i);
            node.addLast(5);
        }
        node.display();
        node.remove(5);
        node.display();
        System.out.println("仅有一个节点:");
        node = new NodeDouble(null);
        node.addLast(5);
        node.display();
        node.remove(5);
        node.display();
    }

    private static void testRemoveAll() {
    
    
        System.out.println("多个节点:");
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 10; i++) {
    
    
            node.addLast(i);
            node.addLast(5);
        }
        node.display();
        node.removeAll(5);
        node.display();
        System.out.println("仅有一个节点:");
        node = new NodeDouble(null);
        node.addLast(5);
        node.display();
        node.removeAll(5);
        node.display();
    }

    private static void testContains() {
    
    
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 5; i++) {
    
    
            node.addLast(i);
        }
        for (int i = 0; i < 10; i++) {
    
    
            System.out.println(i + ": " + node.contains(i));
        }
    }

    private static void testClear(){
    
    
        NodeDouble node = new NodeDouble(null);
        for (int i = 0; i < 5; i++) {
    
    
            node.addLast(i);
        }
        node.display();
        System.out.println("清空:");
        node.clear();
        node.display();
    }
    public static void main(String[] args) {
    
    
        // 放置测试用例
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_45364220/article/details/120172865
今日推荐