所谓双向链表:

  

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

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

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

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

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

如上图: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. Oracle除去换行符的方法

    Oracle除去换行符的方法   很多数据存进数据库后,可能需要将整条数据取出,并用特殊 符号分割,而且整条数据必须是处于一行,如此,如果数据出现 换行的情况,那么读取时就有问题.     这个时候就 ...

  2. winform托盘时,要运行一个实例,解决办法

    需求:winform应用程序,当隐藏到托盘时,再次运行exe程序,让其只运行一个实例,并且把窗口从托盘中显示出来 应用程序名可以通过下面代码,获取到: Process current = Proces ...

  3. 逆向并查集 hrbust 1913

    #include<iostream> //由于拆除并查集的方法太难或者没有#include<cstdio> //可以先将所有没有拆的桥连接 再逆向操作 断开变成连接 反向输出# ...

  4. OpenGL ES 2.0 顶点着色器的妙用

    1.飘扬的旗帜(水面起伏) 基本原理 绘制一帧画面时由顶点着色器根据一定的规则变换各个顶点的位置,即可得到旗帜迎风飘扬的效果. 为了使旗帜的飘动过程比较平滑,采用基于正弦曲线的顶点位置变换规则.

  5. linux 下进程状态及进程控制

    系统状态检测及进程控制1,/proc 是系统的一个窗户,可以透视内核2,建议将hosts里localhost,locahost.locadomain 解析为127.0.0.1 把系统域名解决为局域网的 ...

  6. C#中类的属性

    1.[StructLayout] 控制类或结构的数据字段在托管内存中的物理布局,即类或结构需要按某种方式排列.如果要将类传递给需要指定布局的非托管代码,则显式控制类布局是重要的. 2.[Marshal ...

  7. AFNetworking使用总结

    AFNetworking使用总结   关于AFNetworking使用总结 以及一些错误的解决办法. AD:WOT2015 互联网运维与开发者大会 热销抢票 AFNetworking使用总结 分享类型 ...

  8. hdu Free DIY Tour

    http://acm.hdu.edu.cn/showproblem.php?pid=1224 #include <cstdio> #include <cstring> #inc ...

  9. Unity 3D中的菜单项

    1.File菜单:主要是包含项目和场景的创建.保存以及输出等功能.2.Edit(编辑)菜单:只要包括对场景进行一系列的编辑以及环境设置操作等命令.3.Assets(资源)菜单:掌握资源在Unity中的 ...

  10. WPF:如何实现单实例的应用程序(Single Instance)

    原文:WPF:如何实现单实例的应用程序(Single Instance) 好吧,这是我将WPF与Windows Forms进行比较的系列文章的第四篇,讨论一下如何实现单实例(single instan ...