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

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. UART硬件流控制信号的使用(图)DTR 【转】

    UART硬件流控制信号的使用(图) 转自:http://blog.163.com/zy_tommy/blog/static/86926777201321925451164/ 2013-03-19 14 ...

  2. 【反演复习计划】【COGS2431】爱蜜莉雅的求助

    出题人怎么这么不认真啊==明明官方译名是爱蜜莉雅…… 而且我们爱蜜莉雅碳是有英文名哒!是Emilia.你那个aimiliya我实在是无力吐槽…… 不过抱图跑23333首先这很像约数个数和函数诶!但是唯 ...

  3. 如何在xcode中启用xib方式做应用

    使用storybord的好处和缺点这里不一一说,但是很多人可能习惯xib的方式进行应用的开发. 在xcode环境下可参考如下链接进行设定. http://codefromabove.com/2014/ ...

  4. HTML5-坦克大战一画出敌人坦克并让自己的坦克可以发子弹的功能(二)

    上一篇博客只画出了,一个坦克,并让其可以上下左右移动,这篇博客将画出敌人的坦克,并让自己的坦克可以发子弹,但是还不是尽善尽美,还有一些问题,将会在下篇博客说明: html代码: <!DOCTYP ...

  5. 堆外内存: Chronicle Map

    https://www.javacodegeeks.com/2015/04/chroniclemap-java-architecture-with-off-heap-memory.html Java堆 ...

  6. poj 2826(好坑,线段相交问题)

    An Easy Problem?! Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11576   Accepted: 176 ...

  7. 使用selenium模拟知网登录

    之前都是用phantomjs和selenium模拟浏览器动作的,后来phantomjs不再更新,就转用chrome了 本次模拟登录的网站是中国知网http://login.cnki.net/login ...

  8. hdu4757(可持久化 Trie )

    hdu4757 题意 给出一棵树,每个节点有权值,每次查询节点 \((u, v)\) 以及 \(x\) ,问 \(u\) 到 \(v\) 路径上的某个节点与 \(x\) 异或最大的值是多少. 分析 T ...

  9. 暴力 【p4092】[HEOI2016/TJOI2016]树

    Description 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为1),有以下两种操作: 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其 ...

  10. Codeforces Round #403 (Div. 2, based on Technocup 2017 Finals )D. Innokenty and a Football League(2-sat)

    D. Innokenty and a Football League time limit per test 2 seconds memory limit per test 256 megabytes ...