双向链表

简介

双向链表是基于单链表的基础上,每个节点中添加了一个指向上一个节点的指针。相对单链表而言,双向链表中的增删除改更为方便。例如,双链表可以便捷地进行自我删除的(单链表则需要借助辅助节点),届时只需要需要删除节点的相邻节点进行链接,便可实现自我删除。

功能实现

定义双链表节点

在单链表的基础上,添加一个存储上一个节点的指针。

class Node {
    int no;
    String name;
    Node next;
    Node pre;

    /**
     * 构造函数
     */
    public Node(int no, String data) {
        this.no = no;
        this.name = data;
    }
}

遍历

  • 双链表的遍历也是和单链表一样的。只需要从头结点开始,逐个遍历便可。判断题条件是当前节点的下一个节点不为空(temp.next != null)。
  • 完整代码:
public void printAll() {
    if (headNode.next == null) {
        System.out.println("链表为空~!");
        return;
    }
    Node temp = headNode;
    while (null != temp.next) {
        temp = temp.next;
        System.out.println("编号: " + temp.no + " \t姓名:" + temp.name);
    }
}

顺序添加节点

  • 头节点为空,则直接添加
  • 反之,获取最后一个节点,再添加
  • 需要注意的是,别忘了处理新增节点的上一个指针的地址指向。
  • 完整代码:
/**
 * 添加节点到双向链表的末尾
 *
 * @param node {@link Node} 新增节点
 */
public void add(Node node) {
    Node temp = this.headNode;
    while (null != temp.next) {
        temp = temp.next;
    }
    temp.next = node;
    node.pre = temp;
}

根据内容(Node.name)修改节点

  • 遍历链表,比对索引,相同修改,没有就算了
  • 比较简单,直接贴代码了:
/**
 * 根据索引修改节点内容
 *
 * @param index 节点索引
 * @param name  修改内容
 */
public void modify(int index, String name) {
    if (null == headNode.next) {
        System.out.println("该链表为空~!");
        return;
    }
    Node temp = this.headNode;
    while (null != temp.next) {
        temp = temp.next;
        if (index == temp.no) {
            temp.name = name;
            return;
        }
    }
    System.out.println("没有找到该索引!");
}

通过索引修改整个节点

  • 遍历链表,比对链表,符合则替换整个链表
  • 注意链表的上下指针的指向。
  • 代码实现:
/**
 * 通过索引修改整个节点
 *
 * @param index 节点索引
 * @param node {@link Node} 新的节点
 */
public void modify(int index, Node node) {
    if (this.headNode.next == null) {
        System.out.println("该链表为空~!");
        return;
    }
    Node temp = this.headNode;
    while (null != temp.next) {
        temp = temp.next;
        if (temp.no == index) {
            node.next = temp.next;
            node.pre = temp.pre;
            temp.pre.next = node;
            temp.next.pre = node;
            return;
        }
    }
    System.out.println("没有找到该索引!");
}

通过索引删除节点

  • 代码实现:
/**
 * 删除索引某个节点
 *
 * @param index 节点索引
 */
public void delete(int index) {
    if (this.headNode.next == null) {
        System.out.println("该链表为空~!");
        return;
    }
    Node temp = this.headNode;
    while (null != temp.next) {
        temp = temp.next;
        if (index == temp.no) {
            temp.pre.next = temp.next;
            // 若为链表的最后一个节点,则不用处理 其一个节点的信息
            if (temp.next != null) {
                temp.next.pre = temp.pre;
            }
            return;
        }
    }
    System.out.println("没有找到该节点~!");
}

按顺序添加节点

  • 遍历节点,比较索引,较大者后置
  • 代码实现:
/**
 * 按顺序添加
 *
 * @param node {@link Node} 新增节点
 */
public void addByOrder(Node node) {
    if (this.headNode.next == null) {
        this.headNode.next = node;
        node.pre = this.headNode.next;
        return;
    }
    Node temp = this.headNode;
    while (temp.next != null) {
        temp = temp.next;
        if (temp.no >= node.no) {
            temp.pre.next = node;
            node.pre = temp.pre;
            node.next = temp;
            temp.pre = temp;
            return;
        }
    }
    temp.next = node;
    node.pre = temp;
}

完整代码

因为完整代码比较长,这里就贴一下伪代码就好了,方便查看

  • 完整代码(伪代码):

class DoubleLinkedList {
    /**
     * 双链表的头节点(不作为存储数据的节点)
     */
    private final Node headNode = new Node(0, null);

    /**
     * 按顺序添加
     */
    public void addByOrder(Node node) {
        ···
    }

    /**
     * 删除索引某个节点
     *
     * @param index 节点索引
     */
    public void delete(int index) {
        ····
    }

    /**
     * 通过索引修改整个节点
     *
     * @param index 节点索引
     * @param node {@link Node} 新的节点
     */
    public void modify(int index, Node node) {
        ···
    }

    /**
     * 根据索引修改节点内容
     *
     * @param index 节点索引
     * @param name  修改内容
     */
    public void modify(int index, String name) {
        ···
    }

    /**
     * 添加节点到双向链表的末尾
     *
     * @param node {@link Node} 新增节点
     */
    public void add(Node node) {
        ···
    }

    /**
     * 遍历双向链表
     */
    public void printAll() {
        ···
    }
}

/**
 * 双向链表的节点
 */
class Node {
    int no;
    String name;
    Node next;
    Node pre;

    public Node(int no, String data) {
        this.no = no;
        this.name = data;
    }
}

小结

双链表比单链表多了一个指向上一个节点的指针,真的是太好了,在单链表中需要通过多个临时变量来完成的操作,在双链表中都可以完美快速的解决。总体来说还是很完美的。

老衲
29 声望0 粉丝