Java的单链表()

今天在微信看到一个公众号的推送,感觉这个写的很不错;
https://mp.weixin.qq.com/s/xjWBMIt6sgN6sHUarwIKeA
什么是链表: 链表是一个常见的数据结构,其内部数据呈线性排列,属于线性表结构;
线性表: 表中的数据按顺序依次排列,就想用一条线把数据串列起来一样;
Java的单链表()
文章图片

这种结构特点就是:
【Java的单链表()】优点:添加数据和删除数据比较快;
缺点:查询数据会比较耗时,这是因为链表在内存中的存储的原因;
这里我们可以将数组与链表进行对比,数组大家应该都很熟悉,学过 Java 的都会用,但是你真的了解它在内存中的存储结构吗?数组的特点是查询数据很快,添加数据和删除数据效率低,这一特征与链表恰好相反,数组的缺陷正是链表的优势,数组的优势则是链表的缺陷,所以二者对比着来记,效果会更好。
这两者主要是因为内存中的存储结构的不同;
数组和链表都是线性结构,数组在内存中是一串连续的内存空间,比如定义一个int类型数组,int [] array = new int [6],计算机会为array分配一块连续的空间,如图所示:
Java的单链表()
文章图片

1000-1003 这段空间用来存储数组中的第一个元素 array[0],1004-1007 的空间用来存储 array[1],以此类推数组中的每个元素都对应一块大小为 4 byte 的空间,这种结构就决定了数组查询数据速度很快,只需要知道首地址(在栈内存中记录的就是数组的首地址,可以直接获取),再结合寻址公式就可以很快找到对应元素的地址,从而取出数据。
数组的寻址公式:i_address = first_address + data_size*i
带入上述案例中,比如要找到数组中第 3 个元素,也就是下标为 2 ,该元素的首地址即 2_address = 1000 + 2*4 = 1008,计算机只需要执行一个简单的数学运算就可以找到元素的首地址,进而取出对应的值,对于计算机来讲,简单数学运算的耗时几乎可以忽略不计,所以数组查询数据速度非常快。
也正是因为这种结构导致数组添加和删除数据效率很低,因为这两种操作不仅仅是在数组中添加或者移除一个元素那么简单,同时还需要移动其他已存在的元素。
数组中各个元素的内存地址都是连续,不间断的,删除某个元素之后需要保证数组仍然是连续的,所以就需要移动数据,比如要删除 array[2],删除之后需要依次将 array[3]、array[4]、array[5] 向前移动一位,如下图所示。
Java的单链表()
文章图片

同理,如果此时将 0 添加到数组中的第 2 位,即 array[1] 的位置,同样需要先将 array[1] 及其之后的各个元素依次向后移动 1 位,给新数据腾出位置才能添加,如下图所示。
Java的单链表()
文章图片

因为要移动元素,所以无论是添加数据还是删除数据,效率都不高。

搞清楚数组的存储结构之后,我们再来看看链表的存储结构,在内存中,链表中的数据是分散的,无须存储在一块连续的内存空间中,如下图所示。
Java的单链表()
文章图片

链表中存储了 3 个元素分别是 1、2、3,每个元素都有一个指针,指向下一个元素的内存地址,1 的指针就指向 2 的内存地址 1008,2 的指针就指向 3 的内存地址 1020,依次类推。
不同元素之间的物理空间间隔也是不确定的,所以这样的结构就无法通过一个固定的公式来求出某个元素的内存地址,只能从首元素开始依次向后查找,直到找到目标元素。如果目标元素位于链表的最后一位,则需要遍历整个链表才能找到它,效率很低。
同样,正是因为这样的结构,使得链表添加和删除元素效率很高,无须移动其他已存在的元素,只需要修改元素指针即可。比如,删除 2,则只需要将 1 的指针指向 3 即可,如下图所示。
Java的单链表()
文章图片

所以在链表中,无论是添加还是删除元素,都只需要修改相关节点的指针即可,效率很高。
java实现的代码还在测试未整理出来;


    推荐阅读