数据结构算法学习day5——链表

新星杯·14天创作挑战营·第17期 10w+人浏览 490人参与

一.链表概述

1.定义

在计算机科学中,链表是数据元素的线性集合,其每个元素都指向下一个元素,元素上存储不连续。

2.单向链表代码实现

package com.SinglyLinkedList;

public class SingLinkedList {
    private Node head = null;//头指针

    //节点类(内部类,对外暴露少)
   private static class Node {
        int value;//节点值
        Node next;//下一个节点指针
        //构造方法
        public Node(int value,Node next) {
            this.next = next;
            this.value = value;
        }
   }
    //添加节点
    public void addFirst(int  value) {
        //1.链表为空
        //head =  new Node(value,null);
        //2.链表不为空
        head = new Node(value, head);//这个代码能处理链表非空和链表为空的情况

   }
   //遍历链表
   public void loop1(int[] arr){
       Node p = head;//创建一个指针p,指向头指针head
       while (p != null){
           System.out.print(p.value+" ");
           p = p.next;//移动指针让p指向下一个节点,直到p为null
       }
   }

   public void loop2(int[] arr){
       for (Node p = head; p != null; p = p.next) {
           System.out.print(p.value+" ");
       }
   }

   //查找最后一个节点
    private Node findLast(int value){
        if (head == null){//链表为空的情况
            return null;
        }
        Node p = head;
        for(; p != null; p = p.next){
            if (p.value == value){
                return p;
            }
        }
        return p;
    }

    //添加最后一个节点
    public void addLast(int value){
        Node last = findLast(value);
        if (last == null){
            addFirst(value);
        }else {
            last.next = new Node(value,null);
        }
    }



    //查找索引值
    private Node findNode(int index){
        int i = 0;
        for (Node p = head;p != null;p = p.next,i++) {
            if (i == index){
                return p;//索引值存在,返回该节点
            }
        }
        return null;//索引值不存在
    }

    //获取索引值
    public void get(int index){
       Node node = findNode(index);
       if (node != null){
           System.out.println(node.value);
       }else {
           System.out.println("索引值不存在");
       }
    }

    //往链表的任意一个索引位置加入一个新的元素
    public void insert(int index,int value){
       if (index == 0){
           addFirst(value);//添加第一个节点
       }
       Node node = findNode(index - 1);//表示上一个节点
        if (node == null){//索引值不存在的情况
            addFirst(value);
            return;
        }
       node.next = new Node(value,node.next);//创建一个新节点,插入到指定位置
   }

   //删除第一个位置的索引值
    public void removeFirst(){
       if (head == null){//链表为空的情况
           return;
       }
       head = head.next;//让head指向第二个节点
    }

    //按索引位置来进行删除
    public void remove(int index){
       if (index == 0){ //索引值为0的情况
           removeFirst();//删除第一个节点
           return;
       }
        Node node = findNode(index - 1);//上一个节点
        // 如果当前节点为空,则移除链表的第一个节点并返回
        if (node == null){ //索引值不存在的情况
            removeFirst();
            return;
        }
        // 获取要被删除的下一个节点
        Node removed = node.next;
        // 如果要删除的节点为空,则直接返回
        if (removed == null){ //索引值不存在的情况
            return;
        }
        node.next = removed.next;//删除指定位置的节点
    }

    //单向链表(带哨兵)
    private static class SinglyLinkedList {
       private Node head = new Node(0,null);
    }

}


什么时候要加static?

当某一个内部类使用了外部类的一个成员变量时,就不能加static;而当内部类是相对独立的,跟外部类的成员变量没有任何关系时,这时候就可以加static。

3.带哨兵节点

package com.SinglyLinkedList;

public class SingLinkedList {
    private Node head = new Node(666,null);//头指针

    //节点类(内部类,对外暴露少)
   private static class Node {
        int value;//节点值
        Node next;//下一个节点指针
        //构造方法
        public Node(int value,Node next) {
            this.next = next;
            this.value = value;
        }
   }
    //添加节点
    public void addFirst(int  value) {
   /*     //1.链表为空
        //head =  new Node(value,null);
        //2.链表不为空
        head = new Node(value, head);//这个代码能处理链表非空和链表为空的情况*/
        insert(0,value);

   }
   //遍历链表
   public void loop1(int[] arr){
       Node p = head.next;//创建一个指针p,指向头指针head的下一个节点,跳过了头指针
       while (p != null){
           System.out.print(p.value+" ");
           p = p.next;//移动指针让p指向下一个节点,直到p为null
       }
   }

   public void loop2(int[] arr){
       for (Node p = head.next; p != null; p = p.next) {//要从哨兵的下一个元素开始遍历
           System.out.print(p.value+" ");
       }
   }

   //查找最后一个节点
    private Node findLast(int value){
/*        if (head == null){//链表为空的情况
            return null;
        }*/
        Node p = head;
        for(; p != null; p = p.next){
            if (p.value == value){
                return p;
            }
        }
        return p;
    }

    //添加最后一个节点
    public void addLast(int value){
/*        Node last = findLast(value);
        if (last == null){
            addFirst(value);
        }else {
            last.next = new Node(value,null);
        }*/
        Node last = findLast(value);
        last.next = new Node(value,null);
    }



    //查找索引值
    private Node findNode(int index){
        int i = -1;
        for (Node p = head;p != null;p = p.next,i++) {
            if (i == index){
                return p;//索引值存在,返回该节点
            }
        }
        return null;//索引值不存在
    }

    //获取索引值
    public void get(int index){
       Node node = findNode(index);
       if (node != null){
           System.out.println(node.value);
       }else {
           System.out.println("索引值不存在");
       }
    }

    //往链表的任意一个索引位置加入一个新的元素
    public void insert(int index,int value){
/*       if (index == 0){
           addFirst(value);//添加第一个节点
       }*/
       Node node = findNode(index - 1);//表示上一个节点
        if (node == null){//索引值不存在的情况
            addFirst(value);
            return;
        }
       node.next = new Node(value,node.next);//创建一个新节点,插入到指定位置
   }

   //删除第一个位置的索引值
    public void removeFirst(){
 /*      if (head == null){//链表为空的情况
           return;
       }
       head = head.next;//让head指向第二个节点*/
        remove(0);
    }

    //按索引位置来进行删除
    public void remove(int index){
/*       if (index == 0){ //索引值为0的情况
           removeFirst();//删除第一个节点
           return;
       }*/
        Node node = findNode(index - 1);//上一个节点
        // 如果当前节点为空,则移除链表的第一个节点并返回
        if (node == null){ //索引值不存在的情况
            removeFirst();
            return;
        }
        // 获取要被删除的下一个节点
        Node removed = node.next;
        // 如果要删除的节点为空,则直接返回
        if (removed == null){ //索引值不存在的情况
            return;
        }
        node.next = removed.next;//删除指定位置的节点
    }

    //单向链表(带哨兵)
    private static class SinglyLinkedList {
       private Node head = new Node(0,null);
    }

}


二.双向链表

package com.SinglyLinkedList;

import org.w3c.dom.Node;

public class DoublyLinkedSentinel {
    private Node head;//头指针
    private Node tail;//尾指针

    static class Node{
        Node prev;//上一个节点指针
        int value;//节点值
        Node next;//下一个节点指针

        public Node(Node prev, int value, Node next) {
            this.value = value;
            this.prev = prev;
            this.next = next;
        }
    }
    //创建一个头尾指针
    public DoublyLinkedSentinel(){
        head = new Node(null,666,null);
        tail = new Node(null,888,null);
    }
    //查找指定位置的节点
    private Node findNode(int index){
        int i = -1;
        for(Node p = head;p !=tail; p = p.next,i++){
            if (i == index){
                return p;
            }
        }
        return null;
    }
    //添加首节点
    public void addFirst(int value){
    }
    //删除节点
    public void removeFirst(){
        remove(0);
    }
    //添加尾节点
    public void addLast(int value){
        Node last = tail.prev;
        Node addad = new Node(last,value,tail);
        last.next = addad;
        tail.prev = addad;
    }
    //删除尾节点
    public void removeLast(){
        Node removed = tail.prev;//通过伪哨兵拿到最后一个节点
        if (removed == head){//当删除的节点为头节点时
            //抛异常
            throw new RuntimeException("链表为空");
        }
        Node prev = removed.prev;//拿到前一个节点
        prev.next = tail;//让上一个节点指向伪哨兵
        tail.prev = prev;//再让伪哨兵的prev节点指向前一个节点


    }
    //添加指定位置的节点
    public void insert(int index,int value){
        Node prev = findNode(index - 1);
        if (prev == null){
            //抛异常
            throw new RuntimeException("链表为空");
        }
        Node next = prev.next;
        Node inserted = new Node(prev,value,next);//新节点
        prev.next = inserted;
        next.prev = inserted;
    }
    //删除指定位置的节点
    public void remove(int index){
        Node prev = findNode(index -1);
        if (prev == null){//索引值为空的情况下
            //抛异常
            throw new RuntimeException("链表为空");
        }
        Node removed = prev.next;
        if (removed == tail){//当删除的节点为哨兵节点时
            //抛异常
            throw new RuntimeException("索引值不存在");
        }
        Node next = removed.next;

        prev.next = next;
        next.prev = prev;
    }
}

三.双向环形链表

package com.SinglyLinkedList;

public class DoublyLinkedListSentinel2 {
    private static class Node {
        Node prev;
        int value;
        Node next;

        public Node(Node prev, int value, Node next) {
            this.prev = prev;
            this.value = value;
            this.next = next;
        }
    }

    private  Node sentinel = new Node(null, -1, null);

    public DoublyLinkedListSentinel2() {
        // 创建哨兵节点并让它指向自己形成环形结构
        sentinel.prev = sentinel;
        sentinel.next = sentinel;
    }

    // 添加到第一个节点
    public void addFirst(int value) {
        Node a = sentinel;
        Node b = sentinel.next;
        Node added = new Node(a, value, b);
        a.next = added;
        b.next = added;
    }

    // 添加到最后一个节点
    public void addLast(int value) {
        Node a = sentinel.prev;
        Node b = sentinel;
        Node added = new Node(a, value, b);
        a.next = added;
        b.prev = added;
    }

    // 删除第一个节点
    public void removeFirst() {
        Node removed = sentinel.next;
        if (removed == sentinel) {
            throw new RuntimeException("List is empty");
        }
        Node a = sentinel;
        Node b = removed.next;
        a.next = b;
        b.prev = a;
    }

    // 删除最后一个节点
    public void removeLast() {
        Node removed = sentinel.prev;
        if (removed == sentinel){
            throw new RuntimeException("List is empty");
        }
        Node a = removed.prev;
        Node b = sentinel;
        a.next = b;
        b.prev = a;
    }

    // 查找值
    public Node findByvalue(int value){
        Node p = sentinel.next;
        while (p != sentinel){
            if (p.value == value){
                return p;
            }
            p = p.next;
        }
        return null;
    }

    //根据值来进行删除
    public void remove(int value){
        Node removed = findByvalue(value);
        if (removed == null){
            return;
        }
        Node a = removed.prev;
        Node b = removed.next;
        a.next = b;
        b.prev = a;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值