程序员必会系列之——手写“双向链表”

先赞再看,养成习惯!

在这里插入图片描述

链表作为一种常用的数据结构,我们还是有必要了解一下的,如果有不太了解什么是“链表”的可以查看一下之前的文章。今天让我们动手实现一个“双向链表”。

在这里插入图片描述

双向链表的节点类

public class Node {
  /**
   * 数据域
   */
  public String data;

  /**
   * 指针域(指向下一个节点)
   */
  public Node next;

  /**
   * 指针域(指向前一个节点)
   */
  public Node pre;

  /**
   * 构造方法
   */
  public Node(String data) {
    this.data = data;
  }
}

双向链表(带头节点)的基本代码

public class DoubleLinkedList {

  // 头节点
  private Node herd = new Node("HerdNode");

  public Node getHerd() {
    return herd;
  }

  public void setHerd(Node herd) {
    this.herd = herd;
  }
  
}

在链表尾部添加节点

public void addAfter(Node newNode) {
    // 定义辅助变量,遍历链表使用
    Node temp = herd;
    while (true){
      // 到达列表尾部
      if(temp.next == null){
        break;
      }
      // 后移辅助节点
      temp = temp.next;
    }
    // 在链表尾部添加新节点
    temp.next = newNode; // 将原链表的尾部节点的下一个指针域指向新节点
    newNode.pre = temp; // 将新节点的前一个指针域指向原链表的尾部节点
}

在指定节点内容后插入数据

开始编码前,先看下图,有助于理解代码。

在这里插入图片描述

/**
 * 在指定节点内容后插入数据
 *
 * @param nodeData 指定节点的内容(插入到哪个节点后)
 * @param newNode 新节点
 */
public void insertAfterNode(String nodeData, Node newNode) {
    // 参数校验
    if (nodeData == null) {
      throw new RuntimeException("入参有误!");
    }
    // 定义辅助变量,遍历链表使用
    Node temp = herd;
    // 定义标记,标识找到指定内容的节点
    boolean flag = false;
    while (true) {
      // 到达链表尾部,结束循环。
      if (temp == null) {
        break;
      }
      // 找到指定的节点,结束循环。
      if (nodeData.equals(temp.data)) {
        flag = true;
        break;
      }
      // 将辅助节点后移
      temp = temp.next;
    }
    if (flag) {
      // 注:temp代表的是需要在该节点后插入新节点
      // 判断是否是在链表尾部添加节点
      if (temp.next != null) {
        // 将temp节点的下一个节点的前一个指针域,指向新节点。
        temp.next.pre = newNode;
        // 将新节点的下一个指针域,指向temp节点的下一个节点。
        newNode.next = temp.next;
      }
      // 将temp节点的下一个指针域指向新节点。
      temp.next = newNode;
      // 将新节点的前一个指针域指向temp节点。
      newNode.pre = temp;
    } else {
      throw new RuntimeException("未找到指定节点无法插入新节点!");
    }
}

根据指定节点内容删除节点

为了更好地理解代码,请先看下图。

在这里插入图片描述

/**
 * 删除指定节点
 *
 * @param data 指定节点内容(被删除的节点内容)
 */
public void delete(String data) {
    // 参数校验
    if (data == null) {
      throw new RuntimeException("入参有误!");
    }
    // 定义辅助变量,遍历链表使用
    Node temp = herd;
    // 定义标记,标识找到指定内容的节点
    boolean flag = false;
    while (true){
      // 到达链表尾,结束循环。
      if(temp == null){
        break;
      }
      // 找到待删除的节点
      if(data.equals(temp.data)){
        flag = true;
        break;
      }
      // 后移辅助节点
      temp = temp.next;
    }
    // 判断是否存待删除的节点
    if (flag) {
      // 将待删除节点的前一个节点的下一个指针域,指向待删除节点的下一个节点。
      temp.pre.next = temp.next;
      // 如果是待删除的节点是最后一个节点,就不需要下面这个操作了
      if (temp.next != null) {
        // 将待删除节点的下一个节点的前一个指针域,指向待删除节点的前一个节点。
        temp.next.pre = temp.pre;
      }
    } else {
      System.out.println("未找到要删除的节点!");
    }
}

通过上面的代码和图片相信大家对双向链表会有一个自己的认知,修改和查询相对简单,我就不在演示。有问题的大家可以指出来。感觉文章写的还不错的记得点个赞在走哟。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值