双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。查询即从第一个节点,不断指向下一节点以便获得自己目标节点。删除、插入同理,最后修改目标节点的前后关系即可,以下是模拟实现的过程:

package test;

public class MyLinkedList<E> {

    //先初始化节点类
private static class Node<E>{
E element;//节点数据 Node<E> pre;//上一个节点 Node<E> next;//下一个节点信息 public Node(E element,Node<E> next,Node<E> pre){
this.element = element;
this.pre = pre;
this.next = next;
}
} private int size;//链表的大小 private Node<E> first;//第一个节点 private Node<E> last;//最后一个节点 /**
* 默认往链表尾部添加
* @param e
*/
public void add(E e){
addAtLast(e);
} /**
* 往指定位置添加元素
* @param e
* @param index
*/
public void add(E e,int index){
//先检查是否越界
checkRangeForAdd(index);
if(index == size){//在尾部添加时
addAtLast(e);
}else{
Node<E> curNode = node(index);
addBeforeNode(e, curNode);
}
} /**
* 根据index获取元素
* @param index
* @return
*/
public E get(int index){
//先检查是否越界
checkRange(index);
return node(index).element;
} /**
* 查找元素的下标
* @param element
* @return
*/
public int indexOf(Object element){
Node<E> cursor = first;
int count = ;
while (null != cursor) {
if(null != element){
if(element.equals(cursor.element)){
return count;
}
}else{
if(null == element){//考虑到被查找的元素的为空的情况
return count;
}
} cursor = cursor.next;
count++;
} return -; } /**
* 根据下标删除元素是,处理链表的双向关系
* @param index
* @return
*/
private E deleteLink(int index){
Node<E> node = node(index);
E element = node.element;
Node<E> preNode = node.pre;
Node<E> nextNode = node.next; if(null == preNode){//删除的节点为第一个节点时
first = nextNode;
}else{
preNode.next = nextNode;
node.next = null;
} if (nextNode == null) {//删除的为最后一个节点时
last = preNode;
}else{
nextNode.pre = preNode;
node.pre = null;
}
size--;
node.element = null;
return element; } /**
* 根据index删除元素
* @param index
* @return
*/
public E remove(int index){
//检查数组下标是否越界
checkRange(index);
return deleteLink(index);
} /**
* 根据对象删除
* @param o
* @return
*/
public boolean remove(Object o) {
int index = indexOf(o);
if (index < ){
return false;
}
deleteLink(index);
return true;
} /**
* 检查是否越界
* @param index
*/
private void checkRange(int index) {
if (index >= size || index < ) {
throw new IndexOutOfBoundsException("指定index超过界限");
}
} /**
* 检查是否越界
* @param index
*/
private void checkRangeForAdd(int index) {
if (index > size || index < ) {
throw new IndexOutOfBoundsException("指定index超过界限");
}
}
/**
* 在链表的末尾添加新元素
* @param e
*/
private void addAtLast(E e){ Node<E> oldLast = last; //构造一个新节点
Node<E> node = new Node<E>(e, null, last);
last = node;
if(null == oldLast){//新增元素是第一个元素时
first = node;
}else{//新增元素不是第一个元素时
oldLast.next = node;
}
size ++;
} /**
* 在指定的元素前面添加一个新元素,维持双向的地址
* @param e
* @param curNode
*/
private void addBeforeNode(E e,Node<E> curNode){
Node<E> preNode = curNode.pre;
Node<E> newNode = new Node<E>(e, curNode, preNode); if(null == preNode){//插入到第一个节点前时
first = newNode;
}else{//非第一个节点前时,需维护前一个节点的next指向
preNode.next = newNode;
} curNode.pre = newNode;
size++;
} /**
* 根据index查找元素,只能从头开始找或者从尾部开始找
* @param index
* @return
*/
private Node<E> node(int index){
Node<E> node;
//采用二分查找的方式,将index与size/2的值进行比较,确定是从头开始找,还是从尾部开始找
if (index < (size >> )) {//从头开始找
node = first;
for(int i = ; i < index; i++){
node = node.next;
}
}else{//从尾开始找
node = last;
for(int i = size -; i > index; i--){
node = node.pre;
} } return node;
} /**
* 链表的长度
* @return
*/
public int size(){
return this.size;
} }

Java LinkedList的模拟实现的更多相关文章

  1. Mockito:一个强大的用于Java开发的模拟测试框架

    https://blog.csdn.net/zhoudaxia/article/details/33056093 介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用 ...

  2. java.net.URL 模拟用户登录网页并维持session

    java.net.URL 模拟用户登录网页并维持session 半成品,并非完全有用 import java.io.BufferedReader; import java.io.InputStream ...

  3. 面试题:使用LinkedList来模拟一个堆栈或者队列数据结构

    请使用LinkedList来模拟一个堆栈或者队列数据结构. 堆栈:先进后出 First In Last Out  (FILO) 队列:先进先出 First In First Out  (FIFO) 我 ...

  4. java.net.URL 模拟用户登录网页并维持session【转】

    java.net.URL 模拟用户登录网页并维持session 半成品,并非完全有用 import java.io.BufferedReader; import java.io.InputStream ...

  5. java LinkedList(链表)

    LinkedList也像ArrayList一样实现了基本的List接口,但是它执行某些操作(在List的中间插入和移除)时比ArrayList更高效,但在随机访问方面却要逊色一些 LinkedList ...

  6. 采用LinkedList来模拟栈数据结构的集合--先进后出

    三.用LinkedList来模拟栈数据结构的集合 /* * 自定义一个数据结构为LinkedList的集合类*/public class MyCollection_LinkedList { publi ...

  7. Java LinkedList add vs push

    Java LinkedList add 是加在list尾部. LinkedList push 施加在list头部. 等同于addFirst.

  8. Java LinkedList【笔记】

    Java LinkedList[笔记] LinkedList LinkedList 适用于要求有顺序,并且会按照顺序进行迭代的场景,依赖于底层的链表结构 LinkedList基本结构 LinkedLi ...

  9. java LinkedList (详解)

    Java 链表(LinkedList) 一.链表简介 1.链表 (Linked List) 是一种常见的基础数据结构,是一种线性表,但是链表不会按线性表的顺序存储数据,而是每个节点里存到下一个节点的地 ...

随机推荐

  1. Google开源命令行参数解析库gflags

    Google开源命令行参数解析库gflags http://blog.csdn.net/lming_08/article/details/25072899 CMDLINE的解析 http://blog ...

  2. jQuery重置单选框和input框

    取消选中单选框radio,第一种,第二种方式是使用jQuery实现的,第三种方式是基于JS和DOM实现的,大家可以看看下面的示例 本文提供了三种取消选中radio的方式,代码示例如下: 本文依赖于jQ ...

  3. hdu 5172(线段树||HASH)

    GTY's gay friends Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  4. LUA脚本中O(2)级素数查询

    --================================================================================================== ...

  5. Dijkstra【p3003(bzoj2100)】[USACO10DEC]苹果交货Apple Delivery

    Description 贝西有两个又香又脆的红苹果要送给她的两个朋友.当然她可以走的C(1<=C<=200000)条"牛路"都被包含在一种常用的图中,包含了P(1< ...

  6. 更新archlinux

    有个上网本,虽然配置很差,但是安装的是arch,这不长时间不滚动更新出问题了, :: Proceed with installation? [Y/n] (/) checking keys % (/) ...

  7. RPD Volume 168 Issue 4 March 2016 评论1

    GEANT4 calculations of neutron dose in radiation protection using a homogeneous phantom and a Chines ...

  8. 【分块打表】Gym - 100923K - Por Costel and the Firecracker

    semipal.in / semipal.out Por Costel the pig, our programmer in-training, has recently returned from ...

  9. 【莫队算法】【权值分块】bzoj2223 [Coci 2009]PATULJCI

    不带修改主席树裸题<=>莫队+权值分块裸题. 复杂度O(m*sqrt(n)). P.S.题目描述坑爹,第二个数是权值的范围. #include<cstdio> #include ...

  10. 8.1(java学习笔记)注解(Annotation)

    一.Annotation Annotation不是程序本身,但它可以对程序进行解释,这一点和注释类似. 但最大的不同点在于,注解可以被其他程序读取,然后可以对其进行一些有针对性操作. 这是注解与注释最 ...