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. H5单张、多张图片保存续篇

    前言 这篇是接上篇内容.还没看的可以看H5单张.多张图片上传这篇文章预热. 图片入库 本章我们就来看看如何让多种图片保存至数据库中.数据库:mysql   后端:.NET Core 我们回顾一下上篇我 ...

  2. Redux的中间件原理分析

    redux的中间件对于使用过redux的各位都不会感到陌生,通过应用上我们需要的所有要应用在redux流程上的中间件,我们可以加强dispatch的功能.最近也有一些初学者同时和实习生在询问中间件有关 ...

  3. ConcurrentDictionary并发字典知多少?

    背景 在上一篇文章你真的了解字典吗?一文中我介绍了Hash Function和字典的工作的基本原理. 有网友在文章底部评论,说我的Remove和Add方法没有考虑线程安全问题. https://doc ...

  4. 什么是ZooKeeper?

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

  5. 入门系列之在Ubuntu 16.04使用Buildbot建立持续集成系统

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由angel_郁发表于云+社区专栏 介绍 Buildbot是一个基于Python的持续集成系统,用于自动化软件构建,测试和发布过程. 在 ...

  6. git 的常用命令

    1. 添加远程仓库地址 git remote add origin xxxxxxxxxxxx 2.初始化仓库 git init 3.创建分支 git checkout -b xxxxxx 4. 查看当 ...

  7. 【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限

    开发环境搭建参见<[原]无脑操作:IDEA + maven + SpringBoot + JPA + Thymeleaf实现CRUD及分页> 需求: ① 除了登录页面,在地址栏直接访问其他 ...

  8. Vim中设置括号自动补全

    1.打开用户Vim配置文件:~/.vimrc vim ~/.vimrc 2.输入以下配置: set tabstop=4 inoremap " ""<ESC>i ...

  9. pod command

    pod 基础使用命令 创建Podfile文件 1 pod init 使用命令打开Podfile文件 1 open -a Xcode Podfile 搜索pod 库 1 pod search 库名 更新 ...

  10. kubernetes实战之运行aspnetcore webapi微服务 - kubernetes

    1.预备工作 unbuntu 16.04 or above docker for linux kubernetes for linux 集群环境 2.使用vs2017创建一个web api应用程序,并 ...