Java LinkedList的模拟实现
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。查询即从第一个节点,不断指向下一节点以便获得自己目标节点。删除、插入同理,最后修改目标节点的前后关系即可,以下是模拟实现的过程:
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的模拟实现的更多相关文章
- Mockito:一个强大的用于Java开发的模拟测试框架
https://blog.csdn.net/zhoudaxia/article/details/33056093 介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用 ...
- java.net.URL 模拟用户登录网页并维持session
java.net.URL 模拟用户登录网页并维持session 半成品,并非完全有用 import java.io.BufferedReader; import java.io.InputStream ...
- 面试题:使用LinkedList来模拟一个堆栈或者队列数据结构
请使用LinkedList来模拟一个堆栈或者队列数据结构. 堆栈:先进后出 First In Last Out (FILO) 队列:先进先出 First In First Out (FIFO) 我 ...
- java.net.URL 模拟用户登录网页并维持session【转】
java.net.URL 模拟用户登录网页并维持session 半成品,并非完全有用 import java.io.BufferedReader; import java.io.InputStream ...
- java LinkedList(链表)
LinkedList也像ArrayList一样实现了基本的List接口,但是它执行某些操作(在List的中间插入和移除)时比ArrayList更高效,但在随机访问方面却要逊色一些 LinkedList ...
- 采用LinkedList来模拟栈数据结构的集合--先进后出
三.用LinkedList来模拟栈数据结构的集合 /* * 自定义一个数据结构为LinkedList的集合类*/public class MyCollection_LinkedList { publi ...
- Java LinkedList add vs push
Java LinkedList add 是加在list尾部. LinkedList push 施加在list头部. 等同于addFirst.
- Java LinkedList【笔记】
Java LinkedList[笔记] LinkedList LinkedList 适用于要求有顺序,并且会按照顺序进行迭代的场景,依赖于底层的链表结构 LinkedList基本结构 LinkedLi ...
- java LinkedList (详解)
Java 链表(LinkedList) 一.链表简介 1.链表 (Linked List) 是一种常见的基础数据结构,是一种线性表,但是链表不会按线性表的顺序存储数据,而是每个节点里存到下一个节点的地 ...
随机推荐
- (六)kernel中文件的读写操作可以使用vfs_read()和vfs_write
需要在Linux kernel--大多是在需要调试的驱动程序--中读写文件数据.在kernel中操作文件没有标准库可用,需要利用kernel的一些函数,这些函数主要有: filp_open() fil ...
- time_t转化成日期格式小工具
time_t转化成日期格式小工具下载 http://files.cnblogs.com/files/lansan0701/TimeTool.zip
- PL/SQL 01 代码编写规则
1.标识符命名规则当在 PL/SQL 中使用标识符定义变量.常量时,标识符名称必须以字符开始,并且长度不能超过 30 个字符.另外,为了提高程序的可读性,Oracle 建议用户按照以下规则定义各种标识 ...
- mybatis获取表信息,以及遍历ResultSet
@RunWith(SpringRunner.class) @SpringBootTest public class BravolinksCrmServerApplicationTests { @Aut ...
- html实现点击章节自动调到开头
#转载请联系 原理是用id的值结合a链接实现锚点效果.比较简单,直接放一段代码好了. <!DOCTYPE html> <html lang="en"> &l ...
- springBoot 发布war包
1.packaging 改为war <packaging>war</packaging> 2.剔除内置tomcat <dependency> <groupId ...
- Delphi读写二进制文件
http://www.cnblogs.com/hnxxcxg/p/3691742.html 二进制文件(也叫类型文件),二进制文件是由一批同一类型的数据组成的一个数据序列,就是说一个具体的二进制文件只 ...
- Python 统一动态创建多个model对应的modelForm类(type()函数)
一.ModelForm的用法 ModelForm对用户提交的数据有验证功能,但比Form要简单的多 from django.forms import ModelForm # 导入ModelFormcl ...
- python 如何放心干净的卸载模块
windows系统: C:\selenium-2.43.0>python setup.py install --record ./record.txt C:\selenium-2.43.0> ...
- CF 1009A Game Shopping 【双指针/模拟】
Maxim wants to buy some games at the local game shop. There are n games in the shop, the i-th game c ...