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

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

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

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

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

以下代码采用内部类。

  /**
* 内部类
* @param <E> 泛型
*/
private class Node<E>{
E data;
Node<E> next;
Node<E> pre;
public Node(E data){
this.data=data;
} public Node(E data, Node next, Node pre) {
this.data = data;
this.next = next;
this.pre = pre;
}
public Node(){
next=null;
pre=null;
data=null;
}
public E getData() {
return data;
} public void setData(E data) {
this.data = data;
} public Node getNext() {
return next;
} public void setNext(Node next) {
this.next = next;
} public Node getPre() {
return pre;
} public void setPre(Node pre) {
this.pre = pre;
}
}

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

源代码:

 /**
* @author 李正阳
* @param <E> 泛型
*/
public class MyLinkedList<E> implements List<E> { private Node<E> head=new Node<>();
private int size=0; /**
* 在链表的最后插入元素
* @param data 插入的元素
* @return true 插入成功
*/
@Override
public boolean add(E data) {
Node<E> pNode= head;
while (pNode.getNext()!=null){
pNode=pNode.next;
}
Node<E> temp=new Node(data);
temp.setPre(pNode);
pNode.setNext(temp);
size++;
return true;
} /**
*在number位置添加一个元素
* @param number 在链表中的位置(不是从0开始)
* @return true 添加成功
*/
@Override
public boolean add(int number,E data){
Node<E> pNode=head;
Node<E> temp=new Node<>(data);
for (int i=0;i<number;i++){
pNode= pNode.getNext();
}
pNode.getPre().setNext(temp);
temp.setPre(pNode.getPre());
temp.setNext(pNode.getNext());
pNode.getNext().setPre(temp);
return true;
}
/**
* 判空函数
* @return true 链表为空 false 链表不为空
*/
@Override
public boolean isEmpty() {
if(head.getNext()==null){
return true;
}else {
return false;
}
} /**
* 删除链表中number位置的元素
* @param number 元素在链表中的位置
* @return 删除的那个元素
*/
@Override
public E remove(int number) {
E temp;
Node<E> pNode,preNode;
pNode=head;
for(int i=0;i<number;i++){
pNode=pNode.next;
}
temp=(E) pNode.getData();
preNode=pNode.getPre();
preNode.setNext(pNode.getNext());
pNode.getNext().setPre(preNode);
pNode.setNext(null);
pNode.setPre(null);
pNode=null;
return temp;
} /**
* 尾删法
* @return 删除的那个元素
*/
@Override
public E remove() {
E temp;
Node<E> pNode,preNode;
pNode=head;
while (pNode.getNext()!=null){
pNode=pNode.next;
}
temp=(E) pNode.getData();
preNode=pNode.getPre();
preNode.setNext(null);
pNode.setNext(null);
pNode.setPre(null);
pNode=null;
return temp;
} /**
* 将第i位置的元素替换
* @param i 元素在链表中的位置
* @param data 替换的元素
*/
@Override
public void set(int i, E data) {
Node<E> pNode=head;
for (int j=0;j<i;j++){
pNode=pNode.getNext();
}
pNode.setData(data);
} /**
* 获得链表在i位置的元素
* @param i 元素在i位置的元素
* @return i位置的元素
*/
@Override
public E get(int i) {
E temp;
Node<E> pNode=head;
for (int j=0;j<i;j++){
pNode=pNode.getNext();
}
temp=(E) pNode.getData();
return temp;
} /**
* 检查这条链表现有的是否为回文
* @return true 为回文 false 不为回文
*/
@Override
public boolean isPalindrome() {
Node<E> pNode,nNode;
pNode=head.getNext();
nNode=head;
while (nNode.getNext()!=null){
nNode=nNode.getNext();
}
StringBuilder posSequence=new StringBuilder();
StringBuilder revOrder=new StringBuilder();
while(pNode.getNext()!=null) {
posSequence.append(pNode.getData());
pNode=pNode.getNext();
}
posSequence.append(pNode.getData());
while (nNode.getPre()!=null){
revOrder.append(nNode.getData());
nNode=nNode.getPre();
}
String posequence=posSequence.toString();
String revoredr=revOrder.toString();
if(posequence.equals(revoredr)) {
return true;
}else {
return false;
}
} /**
* 倒置链表
*/
@Override
public void reverseList(){
Node<E> node,nNode;
node=head.getNext();
node.setPre(node.getNext());
node=node.getNext();
nNode=node.getNext();
head.getNext().setNext(null);
while (nNode!=null) {
node.setNext(node.getPre());
node.setPre(nNode);
node=node.getPre();
nNode=node.getNext();
}
node.setNext(node.getPre());
node.setPre(head);
head.setNext(node);
}
/**
* 头插法
* @param data 插入的元素
* @return true 添加成功 false 添加失败
*/
@Override
public boolean addFirst(E data){
Node<E> node=new Node(data);
Node<E> preNode=head.getNext();
head.setNext(node);
preNode.setPre(node);
node.setNext(preNode);
node.setPre(head);
return true;
} /**
* 遍历并输出链表中的元素
*/
@Override
public void traver() {
if(isEmpty()){
System.out.println("链表为空");
}else {
Node<E> pNode = head.getNext();
while (pNode != null) {
System.out.print(pNode.getData() + " ");
pNode = pNode.getNext();
}
}
} /**
* 内部类
* @param <E> 泛型
*/
private class Node<E>{
E data;
Node<E> next;
Node<E> pre;
public Node(E data){
this.data=data;
} public Node(E data, Node next, Node pre) {
this.data = data;
this.next = next;
this.pre = pre;
}
public Node(){
next=null;
pre=null;
data=null;
}
public E getData() {
return data;
} public void setData(E data) {
this.data = data;
} public Node getNext() {
return next;
} public void setNext(Node next) {
this.next = next;
} public Node getPre() {
return pre;
} public void setPre(Node pre) {
this.pre = pre;
}
} }

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

     /**
* 检查这条链表现有的是否为回文
* @return true 为回文 false 不为回文
*/
@Override
public boolean isPalindrome() {
Node<E> pNode,nNode;
pNode=head.getNext();
nNode=head;
while (nNode.getNext()!=null){
nNode=nNode.getNext();
}
StringBuilder posSequence=new StringBuilder();
StringBuilder revOrder=new StringBuilder();
while(pNode.getNext()!=null) {
posSequence.append(pNode.getData());
pNode=pNode.getNext();
}
posSequence.append(pNode.getData());
while (nNode.getPre()!=null){
revOrder.append(nNode.getData());
nNode=nNode.getPre();
}
String posequence=posSequence.toString();
String revoredr=revOrder.toString();
if(posequence.equals(revoredr)) {
return true;
}else {
return false;
}
}
* 算法设计:比较粗暴,直接从链表头到尾将值组成一个String
* 从链表尾到头将值组成一个String
* 然后比较这两个字符串是否相等
链表倒置:
   /**
* 倒置链表
* 算法设计
*/
@Override
public void reverseList(){
Node<E> node,nNode;
node=head.getNext();
node.setPre(node.getNext());
node=node.getNext();
nNode=node.getNext();
head.getNext().setNext(null);
while (nNode!=null) {
node.setNext(node.getPre());
node.setPre(nNode);
node=node.getPre();
nNode=node.getNext();
}
node.setNext(node.getPre());
node.setPre(head);
head.setNext(node);
}
* 算法设计:倒置链表需要修改三处地方,
* 头结点变成尾节点:将pre赋值尾next的引用,next赋值为null
* 尾节点变成头结点:将next赋值为pre,pre赋值为null
* 中间节点将next设置为pre,next设置为pre
												

数据结构学习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. 安全性测试:OWASP ZAP使用入门指南

    免责声明: 本文意在讨论使用工具来应对软件研发领域中,日益增长的安全性质量测试需求.本文涉及到的工具不可被用于攻击目的. 1. 安全性测试 前些天,一则12306用户账号泄露的新闻迅速发酵,引起了购票 ...

  2. CAP带你轻松玩转Asp.Net Core消息队列

    CAP是什么? CAP是由我们园子里的杨晓东大神开发出来的一套分布式事务的决绝方案,是.Net Core Community中的第一个千星项目(目前已经1656 Star),具有轻量级.易使用.高性能 ...

  3. 实现AutoMapper(1.0版本)

    最近有个需求就是实体之间自动转换,网上肯定有很多现成的实现,不过还是自己写了一个,就当对java高级特性的一个熟悉的过程.这中间包含了泛型,反射,lamada表达式.对于想了解java高级特性的人来说 ...

  4. 深度召回模型在QQ看点推荐中的应用实践

    本文由云+社区发表 作者:腾讯技术工程 导语:最近几年来,深度学习在推荐系统领域中取得了不少成果,相比传统的推荐方法,深度学习有着自己独到的优势.我们团队在QQ看点的图文推荐中也尝试了一些深度学习方法 ...

  5. 【4】Asp.Net Core2.2中间件多扩展对应应用

    [前言] 上一篇完成了Asp.Net Core 2.2全新的管道处理模型解析,“俄罗斯套娃”式的委托嵌套和传递,组建了扩展性无与伦比的管道模型!与此同时,委托嵌套过于复杂,使用起来并不友好,然后多种扩 ...

  6. Eclipse4JavaEE安装SpringBoot

    第一步:下载SpringBoot SpringBoot官网下载链接 第二步:在Eclipse里进行安装 打开Eclipse,菜单栏Help ->Install New Software,进入下图 ...

  7. sublime实现markdown浏览器预览

    效果预览 实现 首先下载插件OmniMarkupPreviewer 方法:ctrl + shift + P 安装完成后搜索'OmniMarkupPreviewer'双击即可 下载完成后新建.md文件 ...

  8. 关于'selffilter' is not a registered tag library. Must be one of:

    报错代码: 'selffilter' is not a registered tag library. Must be one of: admin_list admin_modify admin_st ...

  9. Capacitor 新一代混合应用“神器” 会代替Cordova吗??

    1.介绍or畅想 Capacitor是由ionic团队最新开发维护的一个跨平台的应用程序容器,可以轻松构建在iOS,Android,Electron 和 Web 上本机运行的Web应用程序.我们称这些 ...

  10. Spring之旅第二篇-Spring IOC概念及原理分析

    一.IOC概念 上一篇已经了解了spring的相关概念,并且创建了一个Spring项目.spring中有最重要的两个概念:IOC和AOP,我们先从IOC入手. IOC全称Inversion of Co ...