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

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. 只有5行代码的算法——Floyd算法

    Floyd算法用于求一个带权有向图(Wighted Directed Graph)的任意两点距离的算法,运用了动态规划的思想,算法的时间复杂度为O(n^3).具体方法是:设点i到点j的距离为d[i][ ...

  2. 服务器老是出现502 Bad Gateway?

    给你的upstream增加keepalive配置没有? upstream backend { server http://127.0.0.1:8888; keepalive 32; } 在nginx和 ...

  3. MyEclipse10.7安装反编译插件

    jad是一个使用比较广泛的Java反编译软件,jadClipse是jad在eclipse下的插件,下面像大家介绍下如何将jadclipse加入到MyEclipse10.X,9.X,8.X当中: htt ...

  4. 如何调用docker swarm service的API来创建及更新服务

    平衡的推进,先作一个原型吧. #!/usr/bin/env python # -*- coding: utf-8 -*- import requests import json #定义docker s ...

  5. Codeforces Gym100952 A.Who is the winner? (2015 HIAST Collegiate Programming Contest)

      A. Who is the winner?   time limit per test 1 second memory limit per test 64 megabytes input stan ...

  6. 哈希+Bfs【P2730】 魔板 Magic Squares

    没看过题的童鞋请去看一下题-->P2730 魔板 Magic Squares 不了解康托展开的请来这里-->我这里 至于这题为什么可以用康托展开?(瞎说时间到. 因为只有8个数字,且只有1 ...

  7. 学习LSM(Linux security module)之四:一个基于LSM的简单沙箱的设计与实现

    嗯!如题,一个简单的基于LSM的沙箱设计.环境是Linux v4.4.28.一个比较新的版本,所以在实现过程中很难找到资料,而且还有各种坑逼,所以大部分的时间都是在看源码,虽然写的很烂,但是感觉收获还 ...

  8. error和exception的区别

    ------解决方法--------------------------------------------------------了解异常与错误的区别,并且知道当你截获一个异常时,应该怎么办.   ...

  9. 【PKUSC 2015】的一道数学题

    有9个人,每三个人中至少有两个互相认识,求证这里面至少有4个人互相认识 PKU官方题解: 引理:二染色K6中一定有同色K3. 证明:考虑某一个点,它一定连出至少三条同色边(不妨设为红边),这三条边连的 ...

  10. [BZOJ 4144] Petrol

    Link: BZOJ 4144 传送门 Solution: 一道不错的图论综合题 因为只询问关键点,因此重点是要求出关键点之间的最短路,以最短路建图 记$nst[i]$为离$i$最近的关键点:可以发现 ...