通俗易懂的理解list工作原理

本文详细介绍了List作为链表的数据结构,解释了链表如何在内存中以随机存储的方式工作,通过next指针连接各个节点。文章还探讨了单项链表和双向链表的节点构成,并通过实例说明了链表插入新节点的过程,解答了关于节点关联和地址引用的疑问。通过观察head和last变量在插入过程中的变化,澄清了链表动态增长的原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.zf.test.linken;
/**
 * @program: test
 * @description: 测试链表的结构
 * @author: liuzongfang
 * @create: 2019-08-15 09:14
 **/
public class LinkenList {

     //头结点指针
     private Node head;
     //尾结点指针
     private Node last;
     //链表的实际长度
     private int size;
     /**
      * 链表插入元素
      * @param data 插入元素
      * @param index 插入位置
      */
     public void insert(int data,int index) throws Exception{
          if(index<0 || index >size){
               throw new IndexOutOfBoundsException("超出链表结点范围");
          }
          Node insertedNode = new Node(data);
          if(size == 0){
               //空链表
               head = insertedNode;
               last = insertedNode;
          }else if (index == 0){
               //插入头部
               insertedNode.next = head;
               head = insertedNode;
          }else if(size == index){
               //插入尾部
               last.next = insertedNode;
               last = insertedNode;
          }else {
               //中间插入
               Node prevNode = get(index - 1);
               insertedNode.next = prevNode.next;
               prevNode.next = insertedNode;
          }
          size++;
     }
     /**
      * 查找元素链表位置
      * @param index
      * @return
      */
     private Node get(int index){
          if(index < 0 || index >= size){
               throw new IndexOutOfBoundsException("超出链表结点范围!");
          }
          Node temp = head;
          for (int i = 0; i<index ;i++){
               temp = temp.next;
          }
          return temp;
     }
     /**
      * 打印输出链表
      */
     public void output(){
          Node temp = head;
          while (temp!=null){
               System.out.println(temp.data);
               temp = temp.next;
          }
     }

     /**
      * 结点对象
      */
     private static class Node{
               int data;
               Node next;
               Node(int data){
                    this.data = data;
               }
     }
     public static void main(String[] args) {
          LinkenList linkenList = new LinkenList();
          try {
               linkenList.insert(3,0);
               linkenList.insert(7,1);
               linkenList.insert(9,2);
               linkenList.insert(5,3);
               linkenList.insert(6,4);
               linkenList.output();
//               linkenList.(0);
          } catch (Exception e) {
               e.printStackTrace();
          }
     }
}

       首先明白,list是一个链表,链表在内存中种的存储方式是随机储存的,即见缝插针的方式,链表的每一个节点分布在内存中的不同位置,通过next指针像连接,这样可以灵活有效的利用零散的内存空间,前一个结点存储后一个结点的hash地址,

      因此可以可以设计一个单项链表的对象作为一个内存节点,如果是双向链表,可以有三个属性,before,data,next

 /**
      * 结点对象
      */
     private static class Node{
               int data;
               Node next;
               Node(int data){
                    this.data = data;
               }
     }

下面两张图可以比好好的阐述上面的代码,链表是怎么插入新节点,新节点怎么和前一个结点进行关联的

  public void insert(int data,int index) throws Exception{
          if(index<0 || index >size){
               throw new IndexOutOfBoundsException("超出链表结点范围");
          }
          Node insertedNode = new Node(data);
          if(size == 0){
               //空链表
               head = insertedNode;
               last = insertedNode;
          }else if (index == 0){
               //插入头部
               insertedNode.next = head;
               head = insertedNode;
          }else if(size == index){
               //插入尾部
               last.next = insertedNode;
               last = insertedNode;//此时会有一个疑惑,浅层赋值会让last消失
          }else {
               //中间插入
               Node prevNode = get(index - 1);
               insertedNode.next = prevNode.next;
               prevNode.next = insertedNode;
          }
          size++;
     }

如果新的节点信息赋值给last对象,到最后会不会已有一个last对象,此处疑惑了很久,只好使用debug查看地址的引用情况

之后每一次debug都去看下head的变化

看图会发现,当size=0的时候创建了两个对象,一个是head用来确定头结点,一个操作对象last用来后续操作的,

在last =insertedNode 赋值以后会发现原本head的地址是533,last的地址是535, 此时插入的是第二个值,head的next的引用地址指向了 下一个节点对象,

此时插入了第三个结点对象可以发现 next的地址随之发生了改变,通过观察head消除了疑惑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值