线性表-双向链表(LinkedList)
双向链表:如图1-3 所示,会把当前header拆分开,重新插入一个Entry<E>。
LinkedList源码
0.首先这个类中的两个变量
private transient Entry<E> header = new Entry<E>(null, null, null);
private transient int size = 0;
下面的这个size就不用说了,是大小,现在先着重看看 Entry<E> header,
Entry是一个内部类。
- private static class Entry<E> {
- E element;
- Entry<E> next;
- Entry<E> previous;
- Entry(E element, Entry<E> next, Entry<E> previous) {
- this.element = element;
- this.next = next;
- this.previous = previous;
- }
- }


就是一个链表,有父节点和子节点,父子节点都是一个对象的引用。
还有就是这个类是LinkedList的内部类,所以变量自然能再外部直接调用了。
1.构造函数
这个对象在声明的时候已经new了一个对象,所以这里可以直接使用里面的方法
节点的子节点和父节点都自己。
- //无参构造
- public LinkedList() {
- header.next = header.previous = header;
- }

这里是无参构造后header的示意图,父子节点都指向自己。只是最初的header对象。
这里所指向的“一个对象”在初始化中为null 。并且没有改变过。
- //有参构造
- public LinkedList(Collection<? extends E> c) {
- //这一句可不能忘,对头节点的初始化很重要。
- this();
- addAll(c);
- }
在有了添加元素的操作后,entry的指针会指向不同地方。
2.add方法
这个方法主要是讲原来
返回是否成功
- public boolean add(E e) {
- addBefore(e, header);
- return true;
- }
- private Entry<E> addBefore(E e, Entry<E> entry) {
- //新建一个节点,子节点是头结点,这样看来它是环形链表。
- //它的父节点在第一次添加的时候是头结点,以后会得到最后一次添加的节点,并且在下面会断开后重连。
- Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
- //新节点的上一个节点的子节点设置为新的节点
- newEntry.previous.next = newEntry;
- //新节点的下一个节点的父节点设置为新的节点
- newEntry.next.previous = newEntry;
- //大小++
- size++;
- //这个不知道
- modCount++;
- //返回新的节点。
- return newEntry;
- }
- //在第几个位置添加
- public void add(int index, E element) {
- //如果在最后的位置添加,直接和上面的添加一样,如果不是,则
- addBefore(element, (index==size ? header : entry(index)));
- }
- private Entry<E> entry(int index) {
- if (index < 0 || index >= size)
- throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
- //取得头结点
- Entry<E> e = header;
- <span style="color: #ff0000;"> //循环节点,从头节点开始循环,这个处理很聪明,先计算index的大小,小于一半的话正向遍历,大于一半的话反向遍历。</span>
- if (index < (size >> 1)) {
- for (int i = 0; i <= index; i++)
- e = e.next;
- } else {
- for (int i = size; i > index; i--)
- e = e.previous;
- }
- //最后返回节点。
- return e;
- }
- //添加到第一个位置
- public void addFirst(E e) {
- //只是在header的下一个开始添加,不多看了。
- addBefore(e, header.next);
- }
- public void addLast(E e) {
- //这个和add方法一样,所以普通的添加方法也是添加到最后的位置。
- addBefore(e, header);
- }

图1-3
这个是完整的情况,添加,删除都会断开相应的next和previous。同时注意header内部的element不会存储元素。他所指向的对象是null ,在前面也说过。
3.remove
主要是讲要删除元素的Entry调整父子节点就可实现删除。
- public E remove() {
- return removeFirst();
- }
- public E removeFirst() {
- return remove(header.next);
- }
- private E remove(Entry<E> e) {
- //不能删除头节点
- if (e == header)
- throw new NoSuchElementException();
- //这个是用来返回的
- E result = e.element;
- //父节点的子节点指向e的子节点。
- e.previous.next = e.next;
- //子节点的父节点指向e的父节点
- e.next.previous = e.previous;
- //将e设为空。
- e.next = e.previous = null;
- e.element = null;
- //大小--
- size--;
- modCount++;
- return result;
- }
删除元素。这里面的匹配和indexof方法很像。在indexof里面讲。
- public boolean remove(Object o) {
- if (o==null) {
- for (Entry<E> e = header.next; e != header; e = e.next) {
- if (e.element==null) {
- remove(e);
- return true;
- }
- }
- } else {
- for (Entry<E> e = header.next; e != header; e = e.next) {
- if (o.equals(e.element)) {
- remove(e);
- return true;
- }
- }
- }
- return false;
- }
4.indexOf
- //还<span style="color: #ff0000;">是对equals比较</span>
- ,都是正向循环。没什么新意,循环到头指针后结束。
- public int indexOf(Object o) {
- int index = 0;
- if (o==null) {
- for (Entry e = header.next; e != header; e = e.next) {
- if (e.element==null)
- return index;
- index++;
- }
- } else {
- for (Entry e = header.next; e != header; e = e.next) {
- if (o.equals(e.element))
- return index;
- index++;
- }
- }
- return -1;
- }
还有一些找第几个元素,返回元素数量,找到头元素,找都最后元素。
此文转载至:http://wdhdmx.iteye.com/blog/1161972
线性表-双向链表(LinkedList)的更多相关文章
- 数据结构与算法分析java——线性表3 (LinkedList)
1. LinkedList简介 LinkedList 是一个继承于AbstractSequentialList的双向链表.它也可以被当作堆栈.队列或双端队列进行操作.LinkedList 实现 Lis ...
- 【Java数据结构学习笔记之一】线性表的存储结构及其代码实现
应用程序后在那个的数据大致有四种基本的逻辑结构: 集合:数据元素之间只有"同属于一个集合"的关系 线性结构:数据元素之间存在一个对一个的关系 树形结构:数据元素之间存在一个对多个关 ...
- 数据结构与算法分析java——线性表1
说到线性结构的话,我们可以根据其实现方式分为三类: 1)顺序结构的线性表 2)链式结构的线性表 3)栈和队列的线性表 应用程序后在那个的数据大致有四种基本的逻辑结构: 集合:数据元素之间只有&qu ...
- C语言 线性表 双向链式结构 实现
一个双向链式结构实现的线性表 duList (GCC编译). /** * @brief 线性表双向链表结构 * @author wid * @date 2013-10-28 * * @note 若代码 ...
- Java 线性表、栈、队列和优先队列
1.集合 2.迭代器 例子: 3.线性表 List接口继承自Collection接口,有两个具体的类ArrayList或者LinkedList来创建一个线性表 数组线性表ArrayList Linke ...
- 玩转C线性表和单向链表之Linux双向链表优化
前言: 这次介绍基本数据结构的线性表和链表,并用C语言进行编写:建议最开始学数据结构时,用C语言:像栈和队列都可以用这两种数据结构来实现. 一.线性表基本介绍 1 概念: 线性表也就是关系户中最简单的 ...
- [从今天开始修炼数据结构]线性表及其实现以及实现有Itertor的ArrayList和LinkedList
一.线性表 1,什么是线性表 线性表就是零个或多个数据元素的有限序列.线性表中的每个元素只能有零个或一个前驱元素,零个或一个后继元素.在较复杂的线性表中,一个数据元素可以由若干个数据项组成.比如牵手排 ...
- [数据结构-线性表1.2] 链表与 LinkedList<T>(.NET 源码学习)
[数据结构-线性表1.2] 链表与 LinkedList<T> [注:本篇文章源码内容较少,分析度较浅,请酌情选择阅读] 关键词:链表(数据结构) C#中的链表(源码) 可空类 ...
- JAVA中的数据结构——集合类(线性表:Vector、Stack、LinkedList、set接口;键值对:Hashtable、Map接口<HashMap类、TreeMap类>)
Java的集合可以分为两种,第一种是以数组为代表的线性表,基类是Collection:第二种是以Hashtable为代表的键值对. ... 线性表,基类是Collection: 数组类: person ...
随机推荐
- JAVA序列化和反序列化
http://developer.51cto.com/art/201202/317181.htm http://blog.csdn.net/earbao/article/details/4691440 ...
- htm5l,第一个script代码练习
<body> <canvas id="mycanvas" width="500" height="300"> ...
- How to install flashplugin on ubuntu
sudo apt-get install flashplugin-installer
- 8139too.c网卡驱动简单分析
从事linux C开发工作以来,工作内容主要是在应用层,对nginx和unbound等软件有些了解,也常对这2个软件进行二次开发. 对网络这块一直比较有兴趣.也很好奇网卡到底是怎么接受到报文的,以及报 ...
- 踢爆IT劣书出版黑幕——由清华大学出版社之《C语言入门很简单》想到的(1)
1.前言与作者 首先声明,我是由于非常偶然的机会获得<C语言入门很简单>这本书的,绝对不是买的.买这种书实在丢不起那人. 去年这书刚出版时,在CU论坛举行试读推广,我当时随口说了几句(没说 ...
- C++中的4个类型转换关键字
转载:http://poplars.blog.163.com/blog/static/1394221742013021111210567/ n多书里面推荐要养成使用转型关键字的习惯,几年过去了,感觉还 ...
- java udp与tcp
一:基础 NET基本对象java.net.InetAddress类的使用 IP地址是IP使用的32位(IPv4)或者128位(IPv6)位无符号数字,它是传输层协议TCP,UDP的基础.InetAd ...
- PowerShell添加或修改注册表开机启动项脚本
代码如下: $name = Read-Host "请输入开机启动项的名字(随便起)" $value = Read-Host "请输入开机启动项的值" try{ ...
- Discuz的安装 (原创帖,转载请注明出处)
========================写在前面的话========================= 1.LAMP环境搭建请查看这篇日志:http://www.cnblogs.com/yic ...
- nodejs httpserver
用nodejs服务器去拿取后台的数据.(我刚开始学的nodejs的时候是一个蒙圈的宝宝 t.t,开始接触的时候,在本地搭建去拿数据.之前菜鸟的我都不知道路由是神马[囧囧]). --> index ...