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

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;
} }

最新文章

  1. php排序算法
  2. Xcode 生成静态库相关设置:
  3. C# DBHelper 第二版
  4. case break结构与return的有关要点
  5. java实现支付宝接口--文档..转载
  6. 我的android学习经历19
  7. 什么是WEB服务器?
  8. zoj 3778 Talented Chef(思维题)
  9. SQL数据库设计三范式
  10. B树及2-3树的python实现
  11. 【转】VMware Workstation 11 永久激活码key 非注册机
  12. Spark Accumulators
  13. ios应用view之间数据传递的方式
  14. ViewPager用法
  15. [原创*精华]一键发布ASP.NET Web安装程序,搞WebForm的童鞋看过来...
  16. POJ 1584 A Round Peg in a Ground Hole[判断凸包 点在多边形内]
  17. My Stuck in C++
  18. 2,linux入门到上手-ssh安装配置及虚拟机基本使用
  19. 现代C++简单介绍
  20. Django之Models(二)

热门文章

  1. linux内核同步之每CPU变量、原子操作、内存屏障、自旋锁【转】
  2. Maven介绍---POM、Dependency Management、Coordinates
  3. 2.shell变量
  4. Android的简单应用(三)——为你的程序添加监听器
  5. 取消SecureCRT的右击粘贴功能
  6. Selenium2+python自动化24-js处理富文本(带iframe)【转载】
  7. win7 安全模式开启声音
  8. HDU 1754.I Hate It-结构体版线段树(单点更新+区间查询最值)
  9. 基于JS的event-manage事件管理库(一步一步实现)
  10. python3爬虫爬取煎蛋网妹纸图片(上篇)