java基础 之 实现一个链表

引言

1、新建的节点需要两个值:value 和 节点 next;
2、新建的节点链表需要有一个head;
3、根据位置对链表进行添加、删除操作时需要注意判断位置;

链表

链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据部分和指向下一个节点的引用
双向链表中还包括指向前一个节点的引用

节点

在这里插入图片描述

  • 单向节点有两个值:
    • value - 当前节点的值;
    • next - 下一个节点的地址
  • 双向节点有三个值:
    • pre - 前一个节点的地址
    • value - 当前节点的值
    • next - 下一个节点的地址

单向链表

在这里插入图片描述

双向链表

在这里插入图片描述

链表的优缺点

  • 优点

    1、不需要初始化容量,无需在创建时确定大小
    2、插入和删除的时间复杂度是O(1)
    3、如果发生内存回收时,无需大量移动对象,只需改变指针即可

  • 缺点:

    1、访问链表中的元素需要从头开始遍历,时间复杂度为O(n)。
    2、每个链表节点不仅需要存储数据,还需要存储指向前后节点的引用,因此相比数组,链表会占用更多的内存空间

java封装的链表

  • java内部封装了一个LinkedList类

    使用的是双向链表

  • LinkedList集合的一些方法
    LinkedList<String> linkedList = new LinkedList<>();
    
    • boolean add(Object element) 它将元素附加到列表的末尾。
      Boolean b1 = linkedList.add("hello");	//将"hello"添加到链表linkedList的尾部,即尾插法
      
    • boolean add(int index,Object element) 指定位置插入
      Boolean b2 = linkedList.add(3,"java");	//将"java"添加到链表linkedList的第3个位置,即中间插入法
      
    • void addFirst(E element) 元素附加到列表的头部
      Boolean b3 = linkedList.addFirst();	//将"world"添加到链表linkedList的头部,即头插法
      
    • void addLast(E element) 元素附加到列表的尾部
      linkedList.addLast("time");	//将"world"添加到链表linkedList的尾部,即尾插法
      
    • Object get(int index) 根据下标获取数据
      String s1 = linkedList.get(3) ;		//返回linkedList第三个位置的数据
      
    • Object getFirst() 它返回链表的第一个元素。
      String s2 = linkedList. getFirst();		//返回linkedList第一个位置的数据
      
    • Object getLast() 它返回链接列表的最后一个元素
      String s3 = linkedList.getLast() ;		//返回linkedList最后一个元素
      
    • boolean contains(Object element)如果元素存在于列表中,则返回true
      Boolean b4 = linkedList.contains("java");		//如果“java”在linkedList中返回true,不存在返回false
      
    • Object set(int index,Object element)它用于用新元素替换列表中的现有元素
      String s3 = linkedList.set(0,"China") ;		//用“china”替换linkedList第一个位置的数据
      
    • E remove() 删除第一个元素
      String s4 =linkedList.remove() ;		//删除linkedList第一个位置的数据
      
    • E remove(int location) 删除指定位置的元素
      String s5 =linkedList.remove(2) ;		//删除linkedList第2个位置的数据
      
    • E removeFirst() 删除并返回链接列表的头部一个元素
      String s6 =linkedList.removeFirst() ;		//删除并返回linkedList第一个位置的数据
      
    • E removeLast() 删除并返回链接列表的尾部一个元素
      String s7 =linkedList.removeLast()  ;		//返回linkedList第一个位置的数据
      
    • .clear():它删除列表中的所有元素。
      linkedList.clear();		//删除linkedList中的所有元素
      
    • .size() 返回链表长度
      linkedList.size() ;		//返回linkedList的长度
      

自己实现一下链表

以下实现是以单向链表为基准的实现

LinkNode、LinkedList类建议放在同一个包下

LinkNode节点类

public class LinkNode {
    int value;
    LinkNode next;
    // 创建一个节点
    public LinkNode(int value) {
        this.value = value;
    }
    @Override
    public String toString() {
        return "LinkedNode{" + "value=" + value + ", next=" + next + '}';
    }
}

LinkedList类实现

示例图

  • 头插法示例图
    • head为空
      在这里插入图片描述
    • head不为空
      在这里插入图片描述
  • 尾插法示例图
    • head为空:图同头插法
    • head不为空
      在这里插入图片描述
  • 中间插入示例图
    • 插入的位置是0,调用头插法
    • 插入的位置是链表的长度,调用尾插法
    • 0 < 插入的位置 < 链表的长度
      在这里插入图片描述
  • 删除某个节点示例图
    • 判断位置是否合法,根据链表的长度去判断即可,这里不多说了
    • 删除第一个
      在这里插入图片描述

      head = head.next;

    • 删除其他位置
      在这里插入图片描述

      pre = index.next;
      return

代码

public class LinkedList {
    public LinkNode head;

    // 获取链表的长度
    public int length(){
        int count = 0;
        LinkNode index = head;
        while (index!=null){
            index = index.next;
            count++;
        }
        return count;
    }
    // 头插法
    public void headInsert(int value){
        LinkNode node = new LinkNode(value);
        if(head==null){
            head = node;
            return;
        }
        node.next = head;
        head = node;
    }

    // 尾插法
    public void rearInsert(int value){
        LinkNode node = new LinkNode(value);
        LinkNode index = head;
        if(head==null){
            head=node;
            return;
        }
        while(index.next!=null){
            index = index.next;
        }
        index.next = node;
    }

    // 中间插入
    public void add(int position,int value){
        LinkNode node = new LinkNode(value);  // 插入的值的节点

        if(position==0){
            headInsert(value);
        }else if(position==length()){
            rearInsert(value);
        }else{
            LinkNode index = head;  // 遍历的节点
            LinkNode pre = null;  // 遍历节点的前一个节点
            int count = 0; // 用来记录遍历到哪个位置了
            while (index!=null){
                if(position==count){
                    pre.next = node;
                    node.next = index;
                }
                pre = index;  // 将当前的节点赋给pre
                index = index.next;  // 遍历节点往后走
                count++;  // 位置增加
            }
        }
    }

    // 删除
    public void delete(int position){
        // 判断位置是否合法
        if(position<0 || position>=length()){
            System.out.println("删除位置不合法");
        }
        // 首位置删除
        if(position==0){
            head = head.next;
        }else{
            int count = 0;
            LinkNode index = head; // 要遍历的链表的节点
            LinkNode pre = null;    // 用来记录的前一个节点
            while (index!=null){
                // 如果count正好是要删除的位置
                if(count==position){
                    pre.next = index.next;  // 删除成功,返回
                    return;
                }

                // count与要删除的位置不等
                pre = index;    // 记录前一个节点
                index = index.next;     // 记录当前节点
                count++;    // 数值增加
            }
        }

    }
    // 打印值
    @Override
    public String toString() {
        String s = "";
        while(head!=null){
            s+=head.value+" ";
            head = head.next;
        }
        return s;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值