相比ArrayList,双链表的数据结构就复杂多了,想要弄清代码的意思还是要搞清数据结构层面的变化。

  1. package cn.sp.chapter03;
  2.  
  3. import java.util.ConcurrentModificationException;
  4. import java.util.Iterator;
  5. import java.util.NoSuchElementException;
  6.  
  7. /**
  8. * Created by 2YSP on 2017/10/9.
  9. * 实现自己的双链表
  10. */
  11. public class MyLinkedList<AnyType> implements Iterable<AnyType> {
  12.  
  13. private static class Node<AnyType> {
  14.  
  15. public AnyType data;
  16. public Node<AnyType> prev;//指向的前一个节点
  17. public Node<AnyType> next;//指向的后一个节点
  18.  
  19. public Node(AnyType d, Node<AnyType> p, Node<AnyType> n) {
  20. this.data = d;
  21. this.prev = p;
  22. this.next = n;
  23. }
  24. }
  25.  
  26. public MyLinkedList() {
  27. doClear();
  28. }
  29.  
  30. public void clear() {
  31. doClear();
  32. }
  33.  
  34. private void doClear() {
  35. beginMarker = new Node<AnyType>(null, null, null);
  36. endMarker = new Node<AnyType>(null, beginMarker, null);
  37. beginMarker.next = endMarker;
  38.  
  39. theSize = 0;
  40. modCount++;
  41. }
  42.  
  43. public int size() {
  44. return theSize;
  45. }
  46.  
  47. public boolean isEmpty() {
  48. return size() == 0;
  49. }
  50.  
  51. public boolean add(AnyType x) {
  52. add(size(), x);
  53. return true;
  54. }
  55.  
  56. public void add(int idx, AnyType x) {
  57. addBefore(getNode(idx, 0, size()), x);
  58.  
  59. }
  60.  
  61. public AnyType get(int idx) {
  62. return getNode(idx).data;
  63. }
  64.  
  65. public AnyType set(int idx, AnyType newVal) {
  66. Node<AnyType> p = getNode(idx);
  67. AnyType oldVal = p.data;
  68. p.data = newVal;
  69. return oldVal;
  70. }
  71.  
  72. public AnyType remove(int idx) {
  73. return remove(getNode(idx));
  74. }
  75.  
  76. /**
  77. * @param p 添加在该节点前
  78. * @param x 要添加的数据
  79. */
  80. private void addBefore(Node<AnyType> p, AnyType x) {
  81. Node<AnyType> newNode = new Node<>(x, p.prev, p);
  82. newNode.prev.next = newNode;
  83. p.prev = newNode;
  84. theSize++;
  85. modCount++;
  86. }
  87.  
  88. private AnyType remove(Node<AnyType> p) {
  89. p.prev.next = p.next;
  90. p.next.prev = p.prev;
  91. theSize--;
  92. modCount++;
  93. return p.data;
  94. }
  95.  
  96. private Node<AnyType> getNode(int idx) {
  97. return getNode(idx, 0, size() - 1);
  98. }
  99.  
  100. private Node<AnyType> getNode(int idx, int lower, int upper) {
  101. Node<AnyType> p;
  102.  
  103. if (idx < lower || idx > upper) {
  104. throw new IndexOutOfBoundsException();
  105. }
  106.  
  107. if (idx < size() / 2) {
  108. p = beginMarker.next;
  109. for (int i = 0; i < idx; i++) {
  110. p = p.next;
  111. }
  112.  
  113. } else {
  114.  
  115. p = endMarker;
  116. for (int i = size(); i > idx; i--) {
  117. p = p.prev;
  118. }
  119. }
  120.  
  121. return p;
  122. }
  123.  
  124. @Override
  125. public Iterator<AnyType> iterator() {
  126. return new LinkedListIterator();
  127. }
  128.  
  129. private class LinkedListIterator implements java.util.Iterator<AnyType> {
  130.  
  131. private Node<AnyType> current = beginMarker.next;
  132. private int expectedModCount = modCount;
  133. private boolean okToRemove = false;
  134.  
  135. @Override
  136. public boolean hasNext() {
  137. return current != endMarker;
  138. }
  139.  
  140. @Override
  141. public AnyType next() {
  142.  
  143. if (modCount != expectedModCount) {
  144. throw new ConcurrentModificationException();
  145. }
  146.  
  147. if (!hasNext()) {
  148. throw new NoSuchElementException();
  149. }
  150.  
  151. AnyType nextItem = current.data;
  152. current = current.next;
  153. okToRemove = true;
  154.  
  155. return nextItem;
  156. }
  157.  
  158. @Override
  159. public void remove() {
  160. if (modCount != expectedModCount) {
  161. throw new ConcurrentModificationException();
  162. }
  163.  
  164. if (!okToRemove) {
  165. throw new IllegalStateException();
  166. }
  167.  
  168. MyLinkedList.this.remove(current.prev);
  169. expectedModCount++;
  170. okToRemove = false;
  171. }
  172. }
  173.  
  174. private int theSize;
  175. private int modCount = 0;
  176. private Node<AnyType> beginMarker;
  177. private Node<AnyType> endMarker;
  178. }

实现简单版的LinkedList的更多相关文章

  1. JavaMail简单版实验测试

    前言: 最近由于实现web商城的自动发送邮件功能的需求,故涉猎的邮箱协议的内部原理.现将简单版的Java Mail实例做个代码展示,并附上其中可能出现的bug贴出,方便感兴趣的读者进行测试! 1.载入 ...

  2. 小米抢购(简单版v0.1)-登录并验证抢购权限,以及获取真实抢购地址

    小米(简单版)-登录并验证抢购权限,以及获取真实抢购地址! 并不是复制到浏览器就行了的   还得传递所需要的参数 这里只是前部分  后面的自己发挥了 { "stime": 1389 ...

  3. Java实现简单版SVM

    Java实现简单版SVM 近期的图像分类工作要用到latent svm,为了更加深入了解svm,自己动手实现一个简单版的.         之所以说是简单版,由于没实用到拉格朗日,对偶,核函数等等.而 ...

  4. MySQL数据库执行计划(简单版)

    +++++++++++++++++++++++++++++++++++++++++++标题:MySQL数据库执行计划简单版时间:2019年2月25日内容:MySQL数据库执行计划简单版重点:MySQL ...

  5. 红警大战JAVA简单版

    代码结构: 相关源码: 武器类: 属性:武器,攻击力,子弹数量. 方法:给属性赋值(set属性()方法) 获取属性值(get属性()方法) package 红警大战简单版; public class ...

  6. TOJ 3973 Maze Again && TOJ 3128 简单版贪吃蛇

    TOJ3973传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=3973 时间限制(普通 ...

  7. 模板】AC自动机(简单版)

    模板]AC自动机(简单版) https://www.luogu.org/problemnew/show/P3808 这是一道简单的AC自动机模板题. 用于检测正确性以及算法常数. 为了防止卡OJ,在保 ...

  8. PAT 1089 狼人杀-简单版(20 分)(代码+测试点分析)

    1089 狼人杀-简单版(20 分) 以下文字摘自<灵机一动·好玩的数学>:"狼人杀"游戏分为狼人.好人两大阵营.在一局"狼人杀"游戏中,1 号玩家 ...

  9. Go语言之进阶篇简单版并发服务器

    1.简单版并发服务器 示例1: package main import ( "fmt" "net" "strings" ) //处理用户请求 ...

随机推荐

  1. freeswitch三方通话配置

    此种方法能实现,其中默认转移后按0,可进入三方通话. 用transfer只能实现代接转移. Misc. Dialplan Tools att xfer From FreeSWITCH Wiki Jum ...

  2. Python的环境变量设置

    python安装完成后,它的配置很简单,只需要配置下环境变量就可以了. 具体来讲,就是将python的安装目录加入到系统的path中即可.

  3. mysql中如何查询最近24小时、top n查询

    MySQL中如何查询最近24小时. where visittime >= NOW() - interval 1 hour; 昨天. where visittime between CURDATE ...

  4. Duplicate property mapping of contactPhone found in

    启动的时候报Duplicate property mapping of contactPhone found in com....的错误,是因为在建立实体对象的时候,有字段重复了,有的是继承了父类的字 ...

  5. css 滤镜之Gradient

      CreateTime--2017年12月26日11:09:14 Author:Marydon ie滤镜特效之Gradient 作用: 用于设置渐变背景色 使用条件: IE9及以下版本不支持属性ba ...

  6. OSChinaclient源代码学习(2)--缓存的设计

    一.缓存的作用 请求数据的时候,首先进行推断,能否够从缓存中获取数据,假设满足条件,则直接从缓存中获取数据.否则请求新的数据.这样比没有缓存的情况下.每次都要从server请求数据要快,并且.没有网的 ...

  7. 【Mongodb教程 第一课 】 MongoDB下载安装

    MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种.它在许多场景下可用于替代传统的关系型数据库或键/值存储方式.Mongo使用C++开发.以window平台 ...

  8. linux远程管理工具:putty

    使用QTP测试文件上传和目录做成是否成功,必须先将文件和目录下载到本地,再作比较.现在下载工具众多,其中putty是最出色的一个,支持linux服务器,这点很重要“免费的”.下面就让我们来看一下吧! ...

  9. Python开发【第2节】【Python运算符】

    Python语言支持以下类型的运算符: 算术运算符 比较(关系)运算符 赋值运算符 逻辑运算符 位运算符 成员运算符 身份运算符 运算符优先级 1.算术运算符 假设变量a = 10,变量b = 21: ...

  10. 嵌入式开发之命令行---linux下的find文件查找命令与grep文件内容查找命令

    在使用linux时,经常需要进行文件查找.其中查找的命令主要有find和grep.两个命令是有区的. 区别:(1)find命令是根据文件的属性进行查找,如文件名,文件大小,所有者,所属组,是否为空,访 ...