java中没有将指针暴露给用户(以前做过看过一篇文章写有java中是有指针的,只是被藏起来了),所以得使用引用的方式。

何为引用请看下面这篇文章(写的很不错,当然肯定比我写的好):

https://www.cnblogs.com/huajiezh/p/5835618.html

链表中内部类和嵌套类的区别:

https://blog.csdn.net/WelcomeSpring/article/details/79430546

以下代码采用内部类。

  1. /**
  2. * 内部类
  3. * @param <E> 泛型
  4. */
  5. private class Node<E>{
  6. E data;
  7. Node<E> next;
  8. Node<E> pre;
  9. public Node(E data){
  10. this.data=data;
  11. }
  12.  
  13. public Node(E data, Node next, Node pre) {
  14. this.data = data;
  15. this.next = next;
  16. this.pre = pre;
  17. }
  18. public Node(){
  19. next=null;
  20. pre=null;
  21. data=null;
  22. }
  23. public E getData() {
  24. return data;
  25. }
  26.  
  27. public void setData(E data) {
  28. this.data = data;
  29. }
  30.  
  31. public Node getNext() {
  32. return next;
  33. }
  34.  
  35. public void setNext(Node next) {
  36. this.next = next;
  37. }
  38.  
  39. public Node getPre() {
  40. return pre;
  41. }
  42.  
  43. public void setPre(Node pre) {
  44. this.pre = pre;
  45. }
  46. }

E data:存储对象的区域   Node<E> next:引用链表的下一个对象  Node<E> pre;引用链表的上一个对象 所构成了一个双链表

源代码:

  1. /**
  2. * @author 李正阳
  3. * @param <E> 泛型
  4. */
  5. public class MyLinkedList<E> implements List<E> {
  6.  
  7. private Node<E> head=new Node<>();
  8. private int size=0;
  9.  
  10. /**
  11. * 在链表的最后插入元素
  12. * @param data 插入的元素
  13. * @return true 插入成功
  14. */
  15. @Override
  16. public boolean add(E data) {
  17. Node<E> pNode= head;
  18. while (pNode.getNext()!=null){
  19. pNode=pNode.next;
  20. }
  21. Node<E> temp=new Node(data);
  22. temp.setPre(pNode);
  23. pNode.setNext(temp);
  24. size++;
  25. return true;
  26. }
  27.  
  28. /**
  29. *在number位置添加一个元素
  30. * @param number 在链表中的位置(不是从0开始)
  31. * @return true 添加成功
  32. */
  33. @Override
  34. public boolean add(int number,E data){
  35. Node<E> pNode=head;
  36. Node<E> temp=new Node<>(data);
  37. for (int i=0;i<number;i++){
  38. pNode= pNode.getNext();
  39. }
  40. pNode.getPre().setNext(temp);
  41. temp.setPre(pNode.getPre());
  42. temp.setNext(pNode.getNext());
  43. pNode.getNext().setPre(temp);
  44. return true;
  45. }
  46. /**
  47. * 判空函数
  48. * @return true 链表为空 false 链表不为空
  49. */
  50. @Override
  51. public boolean isEmpty() {
  52. if(head.getNext()==null){
  53. return true;
  54. }else {
  55. return false;
  56. }
  57. }
  58.  
  59. /**
  60. * 删除链表中number位置的元素
  61. * @param number 元素在链表中的位置
  62. * @return 删除的那个元素
  63. */
  64. @Override
  65. public E remove(int number) {
  66. E temp;
  67. Node<E> pNode,preNode;
  68. pNode=head;
  69. for(int i=0;i<number;i++){
  70. pNode=pNode.next;
  71. }
  72. temp=(E) pNode.getData();
  73. preNode=pNode.getPre();
  74. preNode.setNext(pNode.getNext());
  75. pNode.getNext().setPre(preNode);
  76. pNode.setNext(null);
  77. pNode.setPre(null);
  78. pNode=null;
  79. return temp;
  80. }
  81.  
  82. /**
  83. * 尾删法
  84. * @return 删除的那个元素
  85. */
  86. @Override
  87. public E remove() {
  88. E temp;
  89. Node<E> pNode,preNode;
  90. pNode=head;
  91. while (pNode.getNext()!=null){
  92. pNode=pNode.next;
  93. }
  94. temp=(E) pNode.getData();
  95. preNode=pNode.getPre();
  96. preNode.setNext(null);
  97. pNode.setNext(null);
  98. pNode.setPre(null);
  99. pNode=null;
  100. return temp;
  101. }
  102.  
  103. /**
  104. * 将第i位置的元素替换
  105. * @param i 元素在链表中的位置
  106. * @param data 替换的元素
  107. */
  108. @Override
  109. public void set(int i, E data) {
  110. Node<E> pNode=head;
  111. for (int j=0;j<i;j++){
  112. pNode=pNode.getNext();
  113. }
  114. pNode.setData(data);
  115. }
  116.  
  117. /**
  118. * 获得链表在i位置的元素
  119. * @param i 元素在i位置的元素
  120. * @return i位置的元素
  121. */
  122. @Override
  123. public E get(int i) {
  124. E temp;
  125. Node<E> pNode=head;
  126. for (int j=0;j<i;j++){
  127. pNode=pNode.getNext();
  128. }
  129. temp=(E) pNode.getData();
  130. return temp;
  131. }
  132.  
  133. /**
  134. * 检查这条链表现有的是否为回文
  135. * @return true 为回文 false 不为回文
  136. */
  137. @Override
  138. public boolean isPalindrome() {
  139. Node<E> pNode,nNode;
  140. pNode=head.getNext();
  141. nNode=head;
  142. while (nNode.getNext()!=null){
  143. nNode=nNode.getNext();
  144. }
  145. StringBuilder posSequence=new StringBuilder();
  146. StringBuilder revOrder=new StringBuilder();
  147. while(pNode.getNext()!=null) {
  148. posSequence.append(pNode.getData());
  149. pNode=pNode.getNext();
  150. }
  151. posSequence.append(pNode.getData());
  152. while (nNode.getPre()!=null){
  153. revOrder.append(nNode.getData());
  154. nNode=nNode.getPre();
  155. }
  156. String posequence=posSequence.toString();
  157. String revoredr=revOrder.toString();
  158. if(posequence.equals(revoredr)) {
  159. return true;
  160. }else {
  161. return false;
  162. }
  163. }
  164.  
  165. /**
  166. * 倒置链表
  167. */
  168. @Override
  169. public void reverseList(){
  170. Node<E> node,nNode;
  171. node=head.getNext();
  172. node.setPre(node.getNext());
  173. node=node.getNext();
  174. nNode=node.getNext();
  175. head.getNext().setNext(null);
  176. while (nNode!=null) {
  177. node.setNext(node.getPre());
  178. node.setPre(nNode);
  179. node=node.getPre();
  180. nNode=node.getNext();
  181. }
  182. node.setNext(node.getPre());
  183. node.setPre(head);
  184. head.setNext(node);
  185. }
  186. /**
  187. * 头插法
  188. * @param data 插入的元素
  189. * @return true 添加成功 false 添加失败
  190. */
  191. @Override
  192. public boolean addFirst(E data){
  193. Node<E> node=new Node(data);
  194. Node<E> preNode=head.getNext();
  195. head.setNext(node);
  196. preNode.setPre(node);
  197. node.setNext(preNode);
  198. node.setPre(head);
  199. return true;
  200. }
  201.  
  202. /**
  203. * 遍历并输出链表中的元素
  204. */
  205. @Override
  206. public void traver() {
  207. if(isEmpty()){
  208. System.out.println("链表为空");
  209. }else {
  210. Node<E> pNode = head.getNext();
  211. while (pNode != null) {
  212. System.out.print(pNode.getData() + " ");
  213. pNode = pNode.getNext();
  214. }
  215. }
  216. }
  217.  
  218. /**
  219. * 内部类
  220. * @param <E> 泛型
  221. */
  222. private class Node<E>{
  223. E data;
  224. Node<E> next;
  225. Node<E> pre;
  226. public Node(E data){
  227. this.data=data;
  228. }
  229.  
  230. public Node(E data, Node next, Node pre) {
  231. this.data = data;
  232. this.next = next;
  233. this.pre = pre;
  234. }
  235. public Node(){
  236. next=null;
  237. pre=null;
  238. data=null;
  239. }
  240. public E getData() {
  241. return data;
  242. }
  243.  
  244. public void setData(E data) {
  245. this.data = data;
  246. }
  247.  
  248. public Node getNext() {
  249. return next;
  250. }
  251.  
  252. public void setNext(Node next) {
  253. this.next = next;
  254. }
  255.  
  256. public Node getPre() {
  257. return pre;
  258. }
  259.  
  260. public void setPre(Node pre) {
  261. this.pre = pre;
  262. }
  263. }
  264.  
  265. }

检查链表所存储是否为回文:

  1. /**
  2. * 检查这条链表现有的是否为回文
  3. * @return true 为回文 false 不为回文
  4. */
  5. @Override
  6. public boolean isPalindrome() {
  7. Node<E> pNode,nNode;
  8. pNode=head.getNext();
  9. nNode=head;
  10. while (nNode.getNext()!=null){
  11. nNode=nNode.getNext();
  12. }
  13. StringBuilder posSequence=new StringBuilder();
  14. StringBuilder revOrder=new StringBuilder();
  15. while(pNode.getNext()!=null) {
  16. posSequence.append(pNode.getData());
  17. pNode=pNode.getNext();
  18. }
  19. posSequence.append(pNode.getData());
  20. while (nNode.getPre()!=null){
  21. revOrder.append(nNode.getData());
  22. nNode=nNode.getPre();
  23. }
  24. String posequence=posSequence.toString();
  25. String revoredr=revOrder.toString();
  26. if(posequence.equals(revoredr)) {
  27. return true;
  28. }else {
  29. return false;
  30. }
  31. }
  1. * 算法设计:比较粗暴,直接从链表头到尾将值组成一个String
    * 从链表尾到头将值组成一个String
    * 然后比较这两个字符串是否相等
    链表倒置:
  1. /**
  2. * 倒置链表
  3. * 算法设计
  4. */
  5. @Override
  6. public void reverseList(){
  7. Node<E> node,nNode;
  8. node=head.getNext();
  9. node.setPre(node.getNext());
  10. node=node.getNext();
  11. nNode=node.getNext();
  12. head.getNext().setNext(null);
  13. while (nNode!=null) {
  14. node.setNext(node.getPre());
  15. node.setPre(nNode);
  16. node=node.getPre();
  17. nNode=node.getNext();
  18. }
  19. node.setNext(node.getPre());
  20. node.setPre(head);
  21. head.setNext(node);
  22. }
  1. * 算法设计:倒置链表需要修改三处地方,
    * 头结点变成尾节点:将pre赋值尾next的引用,next赋值为null
    * 尾节点变成头结点:将next赋值为prepre赋值为null
    * 中间节点将next设置为prenext设置为pre
  1.  

数据结构学习java(一点五)链式顺序表(链表)的更多相关文章

  1. python数据结构与算法第五天【顺序表】

    1.列表存储的两种方式 (1)元素内置方式 采用元素内置的方式只能存放同类型元素的数据类型,例如列表中的元素都为整形,元素类型相同,每个元素存放的地址空间大小也相同,则列表中每个元素都是顺序存放的 ( ...

  2. 7-19 求链式线性表的倒数第K项

    7-19 求链式线性表的倒数第K项(20 分) 给定一系列正整数,请设计一个尽可能高效的算法,查找倒数第K个位置上的数字. 输入格式: 输入首先给出一个正整数K,随后是若干正整数,最后以一个负整数表示 ...

  3. C语言- 基础数据结构和算法 - 栈的链式存储

    听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...

  4. javascript学习(10)——[知识储备]链式调用

    上次我们简单的说了下单例的用法,这个也是在我们java中比较常见的设计模式. 今天简单说下链式调用,可能有很多人并没有听过链式调用,但是其实只要我简单的说下的话,你肯定基本上都在用,大家熟知的jQue ...

  5. guoshiyv 数据结构与算法2-1 线性链式存储

    线性链式存储:   包含两部分:1.存储的单个元素 2.指针,指向下一个的地址 typedef struct() { ElementType Data; struct Node *Next; }Lis ...

  6. 系统学习 Java IO (五)----使用 SequenceInputStream 组合多个流

    目录:系统学习 Java IO---- 目录,概览 SequenceInputStream 可以将两个或多个其他 InputStream 合并为一个. 首先,SequenceInputStream 将 ...

  7. swift学习笔记之-可选链式调用

    //可选链式调用 import UIKit /*可选链式调用(Optional Chaining) 1.在可选值上请求和调用该可选值的属性.方法及下标的方法,如果可选值有值,那么调用就会成功,返回可选 ...

  8. java中的链式编程

    听到链式编程听陌生的,但是写出来就感觉其实很熟悉 package test; public class Test { String name; String phone; String mail; S ...

  9. Java 中的链式编程

    前言 ​ 在写项目的时候,有一个实体类有好多个属性,new 出来之后需要不停的使用setXXX( )方法,效率低而且代码可读性差,查询了下发现可以实现实体类的链式编程. public class Us ...

随机推荐

  1. 什么是ZooKeeper?

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 上次写了一篇 什么是消息队列?以后,本来想入门一下K ...

  2. Node 框架接入 ELK 实践总结

    本文由云+社区发表 作者:J2X 我们都有过上机器查日志的经历,当集群数量增多的时候,这种原始的操作带来的低效率不仅给我们定位现网问题带来极大的挑战,同时,我们也无法对我们服务框架的各项指标进行有效的 ...

  3. SpringBoot系列——利用系统环境变量与配置文件的分支选择实现“智能部署”

    前言 通过之前的博客:SpringBoot系列——jar包与war包的部署,我们已经知道了如果实现项目的简单部署,但项目部署的时候最烦的是什么?修改成发布环境对应的配置!数据库连接地址.Eureka注 ...

  4. docker(1)应用场景以及安装

    今年来了新公司,公司没有用什么新技术,架构就简单的前后分离,但是我推一下新的技术,在这基础上我要培训一下同事,让他们能接受,对新技术不感到陌生,并且认可愿意去学习.其实在这个过程中也能让他们认同我这个 ...

  5. 基础测试jmeter5.0+badboy(从小白到入门)

    1]测试工具jmeter环境安装 1.1]安装jdk环境 1:必须安装jdk8.0(我尝试安装最新版本不行,好像当时没有配置好.之后安装8.0遍可以正常运行)下载地址:单击此段 配置jdk环境:鼠标右 ...

  6. MySQL5.7下面,误操作导致的drop table db1.tb1; 的恢复方法:

    MySQL5.7下面,误操作导致的drop table db1.tb1; 的恢复方法: 0.停业务数据写入.[iptables封禁] 1.从备份服务器上拉取最新的一个全备文件,恢复到一个临时的服务器上 ...

  7. 有源点最短路径--Dijkstra算法

    问题描述:一个带权有向图G与源点v,求从源点v到G中其他顶点的最短路径,并限定各边权值大于0 它的思想在于,对顶点集划分为两组,第一组为已经求出的最短路径的集合(S),期初只有一个顶点,此后每求出一个 ...

  8. 理解Device Tree Usage

    英语原文地址: htttp://devicetree.org/Device_Tree_Usage 本文介绍如何为新的机器或板卡编写设备树(Device Tree), 它旨在概要性的介绍设备树概念,以及 ...

  9. Linux下编译安装php7.2

    准备工作 所有操作需要在root用户下 安装路径: /usr/local/php 安装PHP 首先要安装如下依赖包 $ yum install -y gcc gcc-c++  make zlib zl ...

  10. 怎么用Mac电脑创建多个桌面

    区别于win的单个桌面,Mac电脑可以设置多个桌面,方面用户处理各种多乱杂的情况.究竟怎么用Mac电脑创建多个桌面呢?一起来看看吧! 1.首先打开Mission Control,点击偏好设置 2.然后 ...