0
点赞
收藏
分享

微信扫一扫

单向链表的删除方法

结点的定义:

class Node {
    int val;
    Node next;
  //构造方法
    public Node(int val) {
        this.val = val;
    }
    public Node(int val, Node next) {
        this.val = val;
        this.next = next;
    }
    public Node() {
    }
}

无头链表的删除

准备工作:

public class SingleLinkedList {
  	//创建一个head引用,用于存储头结点的地址
    private Node head;
    private int size;//存储结点个数
}

无头链表中最麻烦的一点就是头结点需要我们特殊处理,因为除了头结点外的结点都有前驱,而头结点没有前驱,因此需要单独考虑

删除链表中索引为index位置的结点

index从0开始计算

public void removeIndex(int index){
  if(head == null){
    //如果没有链表为空,则直接返回
    System.out.println("LinkedList is empty");
    return;
  }
  //判断index的合法性
  if(index < 0 || index >= size){
    System.out.println("remove index illegal");
    return;
  }
  if(index == 0){
    //如果是删除头结点
    Node node = head;//保存头结点
    head = head.next;
    node.next = null;//断开被删除结点的next
    size--;
  }else{
    //不是删除头结点
    Node prev = head;
    for(int i = 0; i< index - 1; i++){
      //从头结点开始,走index-1步到达被删除结点的前驱
      prev = prev.next;
    }
    Node node = prev.next;
    prev.next = node.next;//让前驱结点指向下下个结点
    node.next = null;
    size--;
  }
}

删除链表中第一个元素值为val的结点

我们依然要单独查看第一个结点是否是我们要删除的元素,如果是的话,单独删除

public void removeValOnce(int val){
  if(head == null){
    //如果没有链表为空,则直接返回
    System.out.println("LinkedList is empty");
    return;
  }
  //如果第一个结点就是待删除结点
  if(head.data = val){
    Node node = head;
    head = head.next;
    node.next = null;
    size--;
  }else{
    //如果第一个结点不是待删除结点
    Node prev = head;
    while(prev.next != null){
      if(prev.next.val == val){
        Node node = prev.next;
        prev.next = node.next;
        node.next = null;
        size--;
        return;
      }
      prev = prev.next;
    }
  }
}

删除链表中所有元素值为val的结点

这里值得注意的是:如果头结点元素是待删除结点,删除之后,还需要判断删除后新的头结点是否还是待删除元素,也就是说,不能删除一次head后就走到新的头结点的后继结点

对于头结点以外的删除,我们需要判断前驱结点的后一个结点被删除后,新结点是否还是待删除结点,因此只有当结点不是待删除元素的情况下,前驱结点才能后移

public void removeValAll(int val){
  if(head == null){
    //如果没有链表为空,则直接返回
    System.out.println("LinkedList is empty");
    return;
  }
  //头结点的删除
  while(head != null && head.val == val){
    Node node = head;
    head = head.next;
    node.next = null;
    size--;
  }
  if(head == null){
    //此时链表已经被删完了
    return;
  }
  Node prev = head;
  while(prev.next != null){
    //判断下一个元素是否为待删除元素
    if(prev.next.val == val){
      //删除该元素
      Node node = prev.next;
      prev.next = node.next;
      node.next = null;
      size--;
      //删除后prev不向后走,否则当前prev的下一个元素会因为没有前驱而再也无法删除了
    }else{
      //仅当下一个元素不为待删除元素时向后走
      prev = prev.next;
    }
  }
}

带头链表的删除

从前面的无头单链表的删除来看,我们每一次删除都要单独判断头结点是否为待删除结点

实际上,我们可以引入一个虚拟头结点,该结点只存储了头结点的地址,而不存储元素值,这样一来,对链表的操作来说,每一个结点都带有前驱结点,不再需要为头结点单独考虑

准备工作:

//创建虚拟头结点
Node dummyHead = new Node();
int size = 0;//存储结点个数

删除链表中索引为index位置的结点

public void remove(int index){
    if(dummyHead.next == null){
      	//判断链表是否为空
        System.out.println("LinkedList is empty");
        return;
    }
    if(index < 0 || index >= size){
      	//判断index的合法性
        System.out.println("remove index illegal");
        return;
    }
    Node prev = dummyHead;
    for (int i = 0; i < index; i++) {
      	//让prev一直走到待删除元素的前驱
        prev = prev.next;
    }
  	//删除结点
    Node node = prev.next;
    prev.next = node.next;
    node.next = null;
    size--;
}

删除链表中第一个元素值为val的结点

public void removeValOnce(int val){
    if(dummyHead.next == null){
      	//判断链表是否为空
        System.out.println("LinkedList is empty");
        return;
    }
    Node prev = dummyHead;
    while(prev.next != null){
        if(prev.next.val == val){
          	//找到待删除元素,并删除
            Node node = prev.next;
            prev.next = node.next;
            node.next = null;
            size--;
            return;
        }
      	//如果该结点不是待删除元素,则向后走
        prev = prev.next;
    }
    System.out.println("val does not exist");
}

删除链表中所有元素值为val的结点

public void removeValAll(int val){
    if(size == 0){
        System.out.println("LinkedList is empty");
        return;
    }
    Node prev = dummyHead;
    while(prev.next != null){
      	//为了保证删除一个结点后的下一个结点还是待删除元素
      	//只有在该结点不为val的时候向后移动,否则不动
        if(prev.next.val == val){
            Node node = prev.next;
            prev.next = node.next;
            node.next = null;
            size--;
        }else{
            prev = prev.next;
        }
    }
}
举报

相关推荐

0 条评论