数据结构与算法(四):双向链表

基本概念

双向链表概念和单向链表是一致的,区别在于双向链表在单向链表的基础上,指针区域多了一个指向上一个节点的指针。单向链表内容可以参考我的上一篇文章:http://t.csdn.cn/Iu56H。
基本的数据结构如图所示:

链表结构

双向链表结构包含了节点的数据内容和两个指针:指向前一个节点的preNode,和指向下一个节点的nextNode。

@Data
public class Node {
    // 编号
    private Integer no;
    private String name;
    // 后一个节点
    private Node nextNode;
    // 前一个节点
    private Node preNode;
    public Node(Integer no, String name) {
        this.no = no;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Node{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }
}

链表操作

初始化双向链表

private static Node head = new Node(0, "头节点");

打印链表

/**
 * 打印链表
 */
public void showNode() {
    Node temp = head.getNextNode();
    if (temp == null) {
        System.out.println("链表为空");
        return;
    }
    while (true) {
        System.out.println(temp);
        if (temp.getNextNode() == null) {
            break;
        }
        temp = temp.getNextNode();
    }
}

添加节点(无序)

/**
 * 添加节点
 * @param node
 */
public void addNode(Node node) {
    Node temp = head;
    while (true) {
        if (temp.getNextNode() == null) {
            break;
        }
        temp = temp.getNextNode();
    }
    temp.setNextNode(node);
    node.setPreNode(temp);
}

添加节点(按顺序)

当按照编号大小向链表中添加节点时,需要判断当前的节点是否已经是最后一个节点,如果是最后一个节点,咋只需要将原节点的下一个节点指针指向新节点,新节点的上一个节点指针指向原节点即可。
如果新插入的节点位置在链表中部,则需要对原节点的上一个节点和下一个节点都进行相应的赋值处理。

/**
 * 按顺序插入
 * @param node
 */
public void addNodeSort(Node node) {
    Node temp = head;
    while (true) {
        if (temp.getNo() == node.getNo()) {
            System.out.println("节点已存在:" + node.getNo());
            return;
        }
        // 当前节点比新插入的节点大,需要把新节点放到旧节点前面
        if (temp.getNo() > node.getNo()) {
            node.setPreNode(temp.getPreNode());
            temp.getPreNode().setNextNode(node);
            temp.setPreNode(node);
            node.setNextNode(temp);
            return;
        }
        // 最后一个节点
        if (temp.getNextNode() == null) {
            temp.setNextNode(node);
            node.setPreNode(temp);
            return;
        }
        temp = temp.getNextNode();
    }
}

修改节点内容

/**
* 修改节点内容
* @param node
*/
public void updateNode(Node node) {
   Node temp = head;
   boolean isExist = false;
   while (true) {
       // 未找到要修改的节点
       if (temp == null) {
           break;
       }
       if (temp.getNo() == node.getNo()) {
           isExist = true;
           break;
       }
       temp = temp.getNextNode();
   }
   if (isExist) {
       temp.setName(node.getName());
   } else {
       System.out.println("节点未找到");
   }
}

删除节点

如果删除的节点为链表的最后一个节点,将上一个节点的下一节点指针和自己的上一节点指针设置为null即可。如果删除的节点为中间位置,则需要对删除节点的下一个节点值进行相应的操作使其替换掉要删除的节点,这样要删除的节点没有指针指向后会自动被GC回收。

/**
* 删除节点
* @param no
*/
public void deleteNode(Integer no) {
   Node temp = head;
   while (true) {
       if (temp == null) {
           System.out.println("节点未找到");
           return;
       }
       if (temp.getNo() == no) {
           // 删除的是最后一个节点
           if (temp.getNextNode() == null) {
               temp.getPreNode().setNextNode(null);
               temp.setPreNode(null);
               return;
           } else {
               temp.getPreNode().setNextNode(temp.getNextNode());
               temp.getNextNode().setPreNode(temp.getPreNode());
               return;
           }
       }
       temp = temp.getNextNode();
   }
}

热门相关:洪荒二郎传   不科学御兽   后福   女员工们:2对2交换   大妆