所谓双向链表:

  

(由此图可见老夫深厚的画功)

链表,就是由一个一个的节点连接组成。

在这里,每一个节点都是由三部分组成:上一个节点、当前节点的元素、下一个节点

当链表中只有一个节点的时候,这个节点指向的上一个节点是空的,下一个节点也是空的

当有多个节点的时候,第一个节点的上一个节点是空的,最后一个节点的下一个节点也是空的。

如上图:A节点的下一个节点指向了B节点,B节点的上一个节点指向了A节点

不说了...鉴于本人表达能力有限...直接上代码吧...

 public class MyLinkedList {
     /*第一个节点*/
     private Node first;
     /*最后一个节点*/
     private Node last;
     /*大小*/
     private int size;
     /**
      * 获取这个链表的大小(元素的个数)
      * @return
      */
     public int size(){
         return size;
     }
     /**
      * 这个方法是从LinkedList.node(index)方法中复制过来的,稍加修改
      * 用于返回指点下标处的节点
      * @return
      */
     private Node node(int index){
         /*
          * 打个比方:
          * size = 6;
          * size >> 1 = 3
          * 如果index小于3的话,就从第一个找到最后一个
          * 如果index大于3的话,就从最后一个找到第一个
          * 下面代码亦是如此
          */
         if (index < (size >> 1)) {
             Node x = first;
             for (int i = 0; i < index; i++)
                 x = x.next;
             return x;
         } else {
             Node x = last;
             for (int i = size - 1; i > index; i--)
                 x = x.prev;
             return x;
         }
     }
     /**
      * 增加一个节点
      * @param obj 要增加的元素
      */
     public void add(Object obj){
         Node temp = new Node();//新的节点
         /*新节点的元素赋值*/
         temp.element = obj;

         if (first==null) {//如果第一个节点是空的,那就是没有节点
             //这个节点既然是第一个节点,所以节点的prev点和next都是空的,所以,不用赋值
             //同理,这个新插入的节点是第一个,也是最后一个
             first = temp;
             last = temp;
         }else {//否则,那就意味着这个节点不是空的。
             //新节点的prev就是在这个节点插入前的最后一个节点
             temp.prev = last;
             //而插入前的最后一个节点的next就是这个新的节点了
             //这样,就会形成一条链:a的下一个是b,b的上一个是a,a的下一个是b......
             last.next = temp;
             //最后,新的节点就是最后一个节点了
             last = temp;
         }
         //插入成功size++;
         size++;
     }
     /**
      * 增加一个节点,指定位置
      * @param index
      * @param obj
      */
     public void add(int index, Object obj){
         Node temp = node(index);//得到的节点
         Node newNode = new Node();//新的节点
         newNode.element = obj;

         if (temp!=null) {//如果得到的指定节点不是空的话
             //得到temp的上一个节点
             Node tempPrev = temp.prev;

             //tempPrev的下一个节点赋值为newNode
             tempPrev.next = newNode;
             //同时,newNode的上一个节点赋值为tempPrev
             newNode.prev = tempPrev;

             //然后newNode的下一个节点便是这个一开始就指定的temp节点
             newNode.next = temp;
             //temp的上一个节点赋值为newNode
             //这样在指定元素之前插入了一个新的元素
             temp.prev = newNode;
         }
         size++;
     }
     /**
      * 删除
      * @param index
      */
     public void remove(int index){
         /*
          * 删除...
          * 有 a b c三个元素
          * a的下一个节点是b b的下一个节点是c
          * c的上一个节点是b b的上一个节点是a
          * --
          * 比如删除了b
          * 那就要把a 和 c 连接起来。
          *
          * 连接好了后,就是:
          * a 下一个节点是 c
          * c 上一个节点是 a
          *
          */

         Node temp = node(index);//得到指定下标的元素
         if (temp!=null) {
             /*

             //得到temp的上一个节点
             Node tempPrev = temp.prev;
             //得到temp的下一个节点
             Node tempNext = temp.next;
             //tempPrev的下一个节点是tempNext
             tempPrev.next = tempNext;
             //而tempNext的上一个节点就是tempPrev
             tempNext.prev = tempPrev;

             */

             //temp的上一个节点的下一个节点就是temp的下一个节点
             temp.prev.next = temp.next;
             //temp的下一个节点的上一个节点就是temp的上一个节点
             temp.next.prev = temp.prev;
         }
         size--;
     }
     /**
      * 根据下标获取元素
      * @param index 元素的索引
      * @return
      */
     public Object get(int index){
         return node(index).element;//得到指定节点的元素
     }
     /*------------------------------------------------------------*/
     public static void main(String[] args) {
         MyLinkedList list = new MyLinkedList();
         list.add("a");
         list.add("b");
         list.add(1,"B");
         list.remove(1);
         System.out.println(list.get(1));
         System.out.println("当前链表的大小:"+list.size());
     }
 }
 /**
  * 节点类
  */
 class Node{
     /*
      * 表示上一个节点
      * 所以使用节点类型
      */
     Node prev;
     /*表示下一个节点*/
     Node next;
     /*当前节点的元素*/
     Object element;

     public Node() {
     }

     public Node(Node prev, Node next, Object element) {
         this.prev = prev;
         this.next = next;
         this.element = element;
     }

 }

LinkedList : 双向链表与实现的更多相关文章

  1. JDK1.8 LinkedList双向链表源码

    序言 LinkedList是一个双向链表 也就是说list中的每个元素,在存储自身值之外,还 额外存储了其前一个和后一个元素的地址,所以也就可以很方便地根据当前元素获取到其前后的元素 链表的尾部元素的 ...

  2. JAVA数据结构--LinkedList双向链表

    链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个部分: ...

  3. Java 集合深入理解(11):LinkedList

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情鱼肚白,来学学 LinkedList 吧! 日常开发中,保存一组数据使用的最多的就是 ArrayList, 其次就 ...

  4. LinkedList的自定义实现

    一.背景 LinkedList双向链表: 代码: Node.java: package com.cy.collection; public class Node { Node previous; // ...

  5. 深入理解java集合框架之---------LinkedList

    日常开发中,保存一组数据使用的最多的就是 ArrayList, 其次就是 LinkedList 了. 我们知道 ArrayList 是以数组实现的,遍历时很快,但是插入.删除时都需要移动后面的元素,效 ...

  6. LinkedList 基本示例及源码解析

    目录 一.JavaDoc 简介 二.LinkedList 继承接口和实现类介绍 三.LinkedList 基本方法介绍 四.LinkedList 基本方法使用 五.LinkedList 内部结构以及基 ...

  7. Java集合 LinkedList的原理及使用

    Java集合 LinkedList的原理及使用 LinkedList和ArrayList一样是集合List的实现类,虽然较之ArrayList,其使用场景并不多,但同样有用到的时候,那么接下来,我们来 ...

  8. List集合总结,对比分析ArrayList,Vector,LinkedList

    前面已经写了三篇关于Java集合的文章,包括: Java集合 ArrayList原理及使用 再说Java集合,subList之于ArrayList Java集合 LinkedList的原理及使用 关于 ...

  9. 源码分析(5)-ArrayList、Vector和LinkedList(JDK1.8)

    一.概述 1.线程安全:ArrayList和LinkedList非线程安全的.Vector线程安全的. 2.底层数据结构:ArrayList和Vector底层数据结构是数组:LinkedList双向链 ...

随机推荐

  1. php 之 数据访问 查询关键字 (0506)

    根据数据库中的car表做一个汽车查询页面:  一.一个关键字查询: 主页面: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transiti ...

  2. 对mysql进行分表

    1. 有某个自段进行md5散列,然后生成ord SCII码 $num = ord(md5($user)) //是一个数字 参考 $num/3 ,$num/4;如果我们不是严格意义上的分表,可以参考分布 ...

  3. HTML5 中 div section article 的区别

    刚刚开始接触 HTML5 时,对它的标签很不适应,甚至一度有点反感.尤其是对 div.section.article 这几个标签,实在弄不清楚应该使用在什么场合下. div HTML Spec: Th ...

  4. iOS平台在ffmpeg中使用librtmp

    转载请注明出处:http://www.cnblogs.com/fpzeng/p/3202344.html 系统版本:OS X 10.8 一.在iOS平台上交叉编译librtmp librtmp lin ...

  5. GO实例3 Slice append打印

    package main import "fmt" func main(){ ]int slice:=array[:] slice[]='a' slice[]='b' s1:=ap ...

  6. SQL Fetch size

    JDBC performance tuning with optimal fetch size February 1, 2009 31 Comments Tuning performance usin ...

  7. win10系统加载ahci驱动的操作方案(Win10之家)

    win10系统使用的过程中很多用户会想要加载ahci驱动,但是大部分用户根本不知道怎么操作加载ahci驱动,这样的话很多用户会遇到一些问题,那如果使用的过程中想要加载ahci驱动的话我们应该怎么操作呢 ...

  8. Delphi动态调用Java的WebService 转

    Delphi动态调用Java的WebService —— 基于“Axis2发布WebService例子(HelloWorld)” uses ComObj; var WsObject: Variant; ...

  9. struct2(四)编写Struct2 的Action

    简介: 1.映射一个Action到一个类上面 2.把结果返回到view展示 3.编写Action对应的控制逻辑   1. Action Mapping <action name="he ...

  10. HDU5044---Tree 树链剖分

    大致题意:add1 u v   u到v路径上所有点的权值加上k,add2  u 到v路径上所有边的权值加上k 最后输出所有点的权值,边的权值..树链剖分预处理然后来个线性O(n)的操作.刚开始用线段树 ...