链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
 
 
 
本文是按照《数据结构与算法分析》一书实现的双向链表的内容,个人认为链表的难点在于插入和删除的操作,但这点也是链表的优势之处。
 package DataStructures;

 import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException; public class MyLinkedList<AnyType> implements Iterable<AnyType> {
/*
* data当前节点的值
* prev当前节点的前缀节点
* next当前节点的后缀节点
* */
private static class Node<AnyType>{
public Node(AnyType d,Node<AnyType> p,Node<AnyType> n){
data=d;
prev=p;
next=n;
}
public AnyType data;
public Node<AnyType> prev;
public Node<AnyType> next;
}
public MyLinkedList() {
doClear();
// TODO Auto-generated constructor stub
}
public void clear(){
doClear();
}
/* doClear()
* 将头结点置空
* 尾节点的前缀置为头节点
* 头结点的后缀为尾节点
* */
private void doClear(){
beginMarker=new Node<AnyType>(null, null, null);
endMarker=new Node<AnyType>(null, beginMarker, null);
beginMarker.next=endMarker;
theSize=0;
modCount++;
} public int size(){
return theSize;
}
public boolean isEmpty(){
return size()==0;
}
/*
* 在链表尾部插入新节点
* */
public boolean add(AnyType x){
add(size(), x);
return true;
}
/*
* 在链表中插入新节点
* */
public void add(int idx,AnyType x){
addBefore(getNode(idx,0,size()),x);
}
public AnyType get(int idx){
return getNode(idx).data;
}
/*
* 修改某个节点的值
* */
public AnyType set(int idx,AnyType newVal){
Node<AnyType> p=getNode(idx);//p为需要修改的节点
AnyType oldVal=p.data;
p.data=newVal;
return oldVal;
}
public AnyType remove(int idx){
return remove(getNode(idx));
} /*
* 在p节点前插入新的节点
* */
private void addBefore(Node<AnyType> p,AnyType x){
Node<AnyType> newNode=new Node<>(x, p.prev, p);//新节点的前缀为p的前缀,后缀为p
newNode.prev.next=newNode;//新节点的前缀的后缀为新节点
p.prev=newNode;//p节点的前缀为p
theSize++;
modCount++;
}
private AnyType remove(Node<AnyType> p){
p.next.prev=p.prev;
p.prev.next=p.next;
theSize--;
modCount++;
return p.data;
}
private Node<AnyType> getNode(int idx){
return getNode(idx,0,size()-1);
}
/*
* 获得某个节点
* */
private Node<AnyType> getNode(int idx,int lower,int upper){
Node<AnyType> p;
if(idx<lower||idx>upper)
throw new IndexOutOfBoundsException();
if(idx<size()/2){//如果节点在前半部分,将从头结点向后开始遍历
p=beginMarker.next;
for(int i=0;i<idx;i++)
p=p.next;
}
else {//如果节点在后半部分,将从尾节点向前遍历
p=endMarker;
for(int i=size();i>idx;i--)
p=p.prev;
}
return p;
}
@Override
public Iterator<AnyType> iterator() {
// TODO Auto-generated method stub
return new LinkedListIterator();
}
private class LinkedListIterator implements Iterator<AnyType>{
private Node<AnyType> current=beginMarker;
private int expectedModCount=modCount;
private boolean okToRemove=false;
public boolean hasNext(){
return current!=endMarker;
}
public AnyType next(){
if(modCount!=expectedModCount)
throw new ConcurrentModificationException();
if(!hasNext())
throw new NoSuchElementException();
AnyType nextItem=current.data;
current=current.next;
okToRemove=true;
return nextItem;
}
public void remove(){
if(modCount!=expectedModCount)
throw new ConcurrentModificationException();
if(!okToRemove)
throw new IllegalStateException();
MyLinkedList.this.remove(current.prev);
expectedModCount++;
okToRemove=false;
}
} private int theSize;//链表的长度
private int modCount;//链表改动的次数
private Node<AnyType> beginMarker;//头结点
private Node<AnyType> endMarker;//尾节点
}

JAVA数据结构--LinkedList双向链表的更多相关文章

  1. java数据结构-05双向链表

    一.双向链式存储: ①简述:要是节点中包含两个指针部分,一个指向前驱元,一个指向后继元,Java中LinkedList集合类的实现就是双向链表 (以下图片为网络收集,侵删) ②特点:数据是非连续的,链 ...

  2. Java 数据结构之双向链表

    一.概述: 1.什么是双向链表: 链表中的每个节点即指向前面一个节点,也指向后面一个节点,就像丢手绢游戏一样,每个人都手拉手 2.从头部插入 要对链表进行判断,如果为空则设置尾节点为新添加的节点,如果 ...

  3. 图解Java数据结构之双向链表

    上一篇文章说到了单链表,也通过案例具体实现了一下,但是单链表的缺点也显而易见. 单向链表查找的方向只能是一个方向 单向链表不能自我删除,需要靠辅助节点 而双向链表则能够很轻松地实现上面的功能. 何为双 ...

  4. Java数据结构之双向链表

    管理单向链表的缺点分析: 单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找. 单向链表不能自我删除,需要靠辅助节点 ,而双向链表,则可以自我删除,所以前面我们单链表删除时节点,总是找 ...

  5. Java 的 LinkedList 的底层数据结构

    1. 数据结构--LinkedList源码摘要 public class LinkedList<E> extends AbstractSequentialList<E> imp ...

  6. Java数据结构之表的增删对比---ArrayList与LinkedList之一

    一.Java_Collections表的实现 与c不同Java已经实现并封装了现成的表数据结构,顺序表以及链表. 1.ArrayList是基于数组的实现,因此具有的特点是:1.有索引值方便查找,对于g ...

  7. java通过LinkedList实现堆栈和队列数据结构

    package shb.java.demo3; import java.util.LinkedList; public class TestLinkedList { /** * @author sha ...

  8. Java集合---LinkedList源码解析

    一.源码解析1. LinkedList类定义2.LinkedList数据结构原理3.私有属性4.构造方法5.元素添加add()及原理6.删除数据remove()7.数据获取get()8.数据复制clo ...

  9. Java数据结构之线性表

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

随机推荐

  1. 主机不能访问虚拟机中的web服务【解决方案】

    百度了其它一些方法都不行,最后实在没辙,关了windows防火墙和Linux防火墙,居然能够访问了,我服. 总结一下,原来是Red Hat Linux 6.0防火墙没有开启端口80,开启的方法为(老版 ...

  2. libevent源码深度剖析六

    libevent源码深度剖析六 ——初见事件处理框架 张亮 前面已经对libevent的事件处理框架和event结构体做了描述,现在是时候剖析libevent对事件的详细处理流程了,本节将分析 lib ...

  3. 37.ROUND() 函数

    ROUND() 函数 ROUND 函数用于把数值字段舍入为指定的小数位数. SQL ROUND() 语法 SELECT ROUND(column_name,decimals) FROM table_n ...

  4. Entity Framework 6.0 Tutorials(2):Async query and Save

    Async query and Save: You can take advantage of asynchronous execution of .Net 4.5 with Entity Frame ...

  5. 实践作业3:白盒测试----小组分工讨论DAY2

    白盒测试需要通过检查软件内部的逻辑结构,对软件中的逻辑路径进行覆盖测试;在程序不同地方设立检查点,检查程序的状态,以确定实际运行状态与预期状态是否一致.我们小组在下课时候,在东九教学楼教师休息室进行了 ...

  6. Struts2 配置及运行时遇到问题

    1.java.lang.ClassNotFoundException: org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilt ...

  7. c# as与is的区别

    在c#语言中关于类型的判断与转换有is和as这2种操作符,具体用法如下: is检查一个对象是否兼任与指定的类型,并返回一个Boolean值:true或false,主要,is操作符永远不会抛出异常,一下 ...

  8. 读写文本文件之StreamReader和StreamWriter

    private string _filePath = @"1.txt"; //查询文件是否存在,如果不存在,则创建 if (!File.Exists(_filePath)) { u ...

  9. HTML中&nbsp; &ensp; &emsp; &thinsp;等6种空白空格

  10. MySQL参数log_bin_trust_function_creators

    问题:执行创建函数的sql文件报错如下: [Err] 1418 - This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA ...