转载请注明本文出处:http://www.cnblogs.com/Starshot/p/6918569.html

链表的结构是由一个一个节点组成的,所谓链,就是每个节点的头尾连在一起。而单向链表就是:每个节点包含了当前节点的值和下一个节点引用。双向链表就是每个节点包含了当前节点的值和上下两个节点的引用。相对于数组结构,链表的增删效率会更加高。

这边文章主要讲怎么用Java实现一个简单的链表结构:单向无环链表。以及实现一些数据处理的方法。

首先,新建一个节点类(本次例子中的节点值都是字符串类型):

 public class Node {

     private String value;
private Node next; public Node(String value){
this.value=value;
}
public Node(){ } public String getValue(){
return value;
} public Node getnext(){
return next;
} public void setValue(String value){
this.value=value;
} public void setNext(Node next){
this.next=next;
}
}

然后再建一个链表类:

public class MyLinkedTable {

    Node head=new Node();

    //向链表中增加值
public boolean add(String str){
Node node=new Node(str);
if(head.getnext()==null){
head.setNext(node);;
return true;
} Node tmp=head; while(tmp.getnext()!=null){
tmp=tmp.getnext();
} tmp.setNext(node); return true; }
//已知某个节点,然后删除该节点
public boolean delete(Node node){
Node next=node.getnext();
Node nextAddress=next.getnext();
String nextValue=next.getValue();
node.setNext(nextAddress);
node.setValue(nextValue);
return true;
} //删除第index个节点,index从1开始
public boolean delete(int index){ if(index>length()||index<1){
return false;
} int i=1;
Node temp=head.getnext();
while(i<index){
temp=temp.getnext();
i++;
} Node next=temp.getnext();
Node nextAddress=next.getnext();
String nextValue=next.getValue();
temp.setNext(nextAddress);
temp.setValue(nextValue); return true;
} //获得第index个节点的值
public String get(int index){
if(index>length()||index<1){
return null;
} int i=1;
Node temp=head.getnext();
while(i<index){
temp=temp.getnext();
i++;
} return temp.getValue();
} //获取链表里面数据的长度,也就是插入了多少个值。
public int length(){ if(head.getnext()==null){
return 0;
} int i=1;
Node temp=head.getnext();
while((temp=temp.getnext())!=null){
i++;
} return i;
} //反转链表
public void reverseTable(){
Node node1=head.getnext(); if(node1==null){
return;
} Node preNode=null;
Node curNode=node1; while(true){
Node origNextNode=curNode.getnext();
curNode.setNext(preNode);
if(origNextNode==null){
head.setNext(curNode);
break;
}
preNode=curNode;
curNode=origNextNode;
} } //获取中间链表
public String getMid(){ Node slowPointer=this.head.getnext(),fastPointer=this.head.getnext();
while(fastPointer!=null&&fastPointer.getnext()!=null&&fastPointer.getnext().getnext()!=null){
slowPointer=slowPointer.getnext();
fastPointer=fastPointer.getnext().getnext();
} return slowPointer.getValue(); } //删除重复链表
public void deleteDuplicateNode(){
Node nodeCur=head.getnext(); if(nodeCur==null) return; while(nodeCur.getnext()!=null){
Node lastNode=nodeCur;
Node compareNode=lastNode.getnext();
while(compareNode!=null){ if(nodeCur.getValue().equals(compareNode.getValue())){
lastNode.setNext(compareNode.getnext());
compareNode=compareNode.getnext();
}else{ lastNode=compareNode;
compareNode=compareNode.getnext();
}
}
nodeCur=nodeCur.getnext();
}
}
}

需要说明一下,这个链表结构是以head为起始节点,head指向插入的第一个节点(反转后就是最后一个),head本身的value一直都是空的,它只作为起始节点入口存在,不参与节点的计数,所以链表的节点总数(插入数据总数)是不包括head在内的。

接下来对某些方法进行说明:

1.链表反转

//链表翻转就是把原来的1>2>3>4变成4>3>2>1,所以原来在最前面的节点要变成在最后面,最后面的要变成最前面
//就是head的地址引用要变成最后一个节点的,原来head后的第一个节点的地址引用要由第二的节点变为NULL,原来第二个节点的地址引用要由第三个节点变成第一个节点
//以此类推,一直翻转到最后一个。然后把head的地址引用变成最后一个。
//在这个链表里面,head的位置是一直不变的,它永远是最前面,在head之后的节点才开始翻转。
public void reverseTable(){
Node node1=head.getnext(); if(node1==null){
return;
} Node preNode=null;
Node curNode=node1; while(true){
Node origNextNode=curNode.getnext();
curNode.setNext(preNode);
if(origNextNode==null){
head.setNext(curNode);
break;
}
preNode=curNode;
curNode=origNextNode;
} }

2.获得中间节点:

//通过用快慢指针来找到中间节点,快指针的速度为慢指针的两倍,慢指针一次走一个节点,快指针一次走两个节点,
//当快指针走到尽头时,慢指针刚好为中间值,当快指针走到倒数第二个节点时,慢指针为上中位数。
//fastPointer!=null用来判断链表表内除head外有没有其它节点,fastPointer.getnext()!=null判断是否为最后一个节点,
//fastPointer.getnext().getnext()!=null判断是否为倒数第二个节点。
public String getMid(){ Node slowPointer=this.head.getnext(),fastPointer=this.head.getnext();
while(fastPointer!=null&&fastPointer.getnext()!=null&&fastPointer.getnext().getnext()!=null){
slowPointer=slowPointer.getnext();
fastPointer=fastPointer.getnext().getnext();
} return slowPointer.getValue(); }

3.删除具有相同值的节点(重复节点):

//删除具有相同值的节点
//基本原理是用第一个节点的值和第二个节点值比较,然后和第三个节点比较,以此类推。此时第一个节点为当前节点nodeCur,第二第三以及之后的节点为比较节点compareNode
//一轮比较完毕后,第二个节点就变成nodeCur,之后那些节点就是compareNode
//如果遇到有相同的值的节点,就将该节点的上个节点的next值为该节点的下个节点:lastNode.setNext(compareNode.getnext()),此时该节点就在链表里失去引用了,就相当于删除了。
//所以需要lastNode引用来保存当前比较节点的上一个节点
public void deleteDuplicateNode(){
Node nodeCur=head.getnext(); if(nodeCur==null) return; while(nodeCur.getnext()!=null){
Node lastNode=nodeCur;
Node compareNode=lastNode.getnext();
while(compareNode!=null){ if(nodeCur.getValue().equals(compareNode.getValue())){
lastNode.setNext(compareNode.getnext());
compareNode=compareNode.getnext();
}else{ lastNode=compareNode;
compareNode=compareNode.getnext();
}
}
nodeCur=nodeCur.getnext();
}
}

写好之后可以测试一下:

public class Test {

    public static void main(String[] args) {

        MyLinkedTable m=new MyLinkedTable();
m.add("1");
m.add("2");
m.add("3");
m.add("4");
m.add("5");
m.add("6"); for(int i=1;i<=m.length();i++){
System.out.println(i+":"+m.get(i));
}
System.out.println("length:"+m.length()); m.reverseTable();
for(int i=1;i<=m.length();i++){
System.out.println(i+":"+m.get(i));
}
System.out.println("length:"+m.length()); m.delete(2);
for(int i=1;i<=m.length();i++){
System.out.println(i+":"+m.get(i));
}
System.out.println("length:"+m.length()); System.out.println(m.getMid()); } }

运行输出如下:

1:1
2:2
3:3
4:4
5:5
6:6
length:6
1:6
2:5
3:4
4:3
5:2
6:1
length:6
1:6
2:4
3:3
4:2
5:1
length:5
3

还有测试删除重复节点的:

public class Test2 {

    public static void main(String[] args) {
MyLinkedTable m=new MyLinkedTable();
m.add("1");
m.add("2");
m.add("3");
m.add("2");
m.add("2");
m.add("6"); for(int i=1;i<=m.length();i++){
System.out.println(i+":"+m.get(i));
}
System.out.println("length:"+m.length()); m.deleteDuplicateNode(); for(int i=1;i<=m.length();i++){
System.out.println(i+":"+m.get(i));
}
System.out.println("length:"+m.length());
} }

运行输出:

1:1
2:2
3:3
4:2
5:2
6:6
length:6
1:1
2:2
3:3
4:6
length:4

以上就是用java实现单向无环链表的详细过程和解释,如果不妥之处,欢迎指出。

(原创)用Java实现链表结构对象:单向无环链表的更多相关文章

  1. JavaScript实现单向链表结构

    参考资料 一.什么是链表结构? 1.1.简介 链表和数组一样, 可以用于存储一系列的元素, 但是链表和数组的实现机制完全不同,链表中的元素在内存不是连续的空间,链表的每个元素由一个存储元素本身(数据) ...

  2. 【二叉树->链表】二叉树结构转双向线性链表结构(先序遍历)

    二叉树存储结构属于非线性链表结构,转化成线性链表结构,能简化操作和理解.然而由非线性转线性需要对整个树遍历一次,不同的遍历方式转化结果页不一样.下面以先序为例. 方法一: 递归法.递归遍历二叉树,因为 ...

  3. Linux内核--链表结构(一)

    一.前言 Linux内核链表结构是一种双向循环链表结构,与传统的链表结构不同,Linux内核链表结构仅包含前驱和后继指针,不包含数据域.使用链表结构,仅需在结构体成员中包含list_head*成员就行 ...

  4. 《Java数据结构》链表结构(单向链表,双向链表)

    单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始:链表是使用指针进行构造的列表:又称为结点列表,因为链表是由一个个结点组装起来的:其中每个结点都有指 ...

  5. JAVA基础——链表结构之单链表

    链表:一种数据存储结构.学链表首先要搞懂数组,按朋友的话说,数组和链表的关系就相当于QQ2008和QQ2009. 除非要通过索引频繁访问各个数据,不然大多数情况下都可以用链表代替数组. 链表部分主要要 ...

  6. Atitit 跨平台异常处理(2)--------异常转换 -----java c# js异常对象结构比较and转换

    Atitit 跨平台异常处理(2)--------异常转换 -----java c# js异常对象结构比较and转换 { "@type":"java.lang.Runti ...

  7. 由PHP实现单向链表引发的对象赋值,对象传参,链表操作引发的一系列问题

    2019年2月25日14:21:13 测试版本php 5.4 ,5.6,7.0,7.2 代码请看: https://www.cnblogs.com/zx-admin/p/10373866.html 1 ...

  8. 面试题:JVM在Java堆中对对象的创建、内存结构、访问方式

    一.对象创建过程 1.检查类是否已被加载 JVM遇到new指令时,首先会去检查这个指令参数能否在常量池中定位到这个类的符号引用,检查这个符号引用代表的类是否已被加载.解析.初始化,若没有,则进行类加载 ...

  9. java实现链表结构详细代码

    一.数据准备 1. 定义节点 2.   定义链表 1.数据部分 2.节点部分 class DATA //数据节点类型 { String key; String name; int age; } cla ...

随机推荐

  1. MySql字符串函数使用技巧

    1.从左开始截取字符串 left(str, length) 说明:left(被截取字段,截取长度) 例:select left(content,200) as abstract from my_con ...

  2. C字符串处理函数

    部分参考百科. C常用字符串函数:字符串输入函数,字符串输出函数,字符串处理函数,标准输入输出流 字符串处理函数: 1.字符串长度:strlen(str),返回字符串实际长度,不包括'\0',返回值类 ...

  3. My SQL数据库的安装与配置

    MySQL是一个关系型数据库管理系统.MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言 MySQL 软件采用了双授权政策,分为社区版和商业版,由于其体积小.速度快.总体拥有成本低,尤 ...

  4. (函数封装)domReady

    一般的我们用window.onload()来判断文档是否加载完成,我们一般采用下面的做法: 当文档加载全部完后,我们在执行代码块(很显然,当需要加载的文档及节点庞大时,用户体验可能会变很差) wind ...

  5. Linux系统管理10——进程和计划任务管理

    Linux系统管理10——进程和计划任务管理 一.程序和进程的关系 1.程序 ·保存在硬盘.光盘等介质中的可执行代码和数据 ·静态保存的代码 2.进程 ·在CPU及内存中运行的程序代码 ·动态执行的代 ...

  6. NodeJS+Express+MongoDB 简单实现数据录入及回显展示【适合新人刚接触学习】

    近期在看NodeJS相关 不得不说NodeJS+Express 进行网站开发是很不错,对于喜欢玩JS的来说真是很好的一种Web开发组合 在接触NodeJS时受平时Java或者C#中API接口等开发的思 ...

  7. tpcc-mysql安装

    1.因为我的虚拟机是centos 7 min版本,所以先得安装gcc gcc++: http://mirror.centos.org/centos/7/os/x86_64/Packages/   rp ...

  8. [故障公告]14:39-15:39博客站点部分负载均衡遭遇3次20G以上的流量攻击

      非常抱歉,今天下午14:39-15:39左右,博客站点的部分负载均衡遭遇3次20G以上的流量攻击,造成很多用户不能正常访问.由此给您带来麻烦,请您谅解. 攻击的过程是这样的: 14:39,第1次攻 ...

  9. 将sublimeText添加到鼠标右键菜单栏

    将sublimeText添加到鼠标右键菜单栏主要是写一个注册表的文件,将这个注进去,首先你需要清楚你的sublimeText软件的安装路径,然后改一下下面这段代码就可以了 Windows Regist ...

  10. 学习笔记:javascript 表单对象(form)

    Form 对象属性 属性 描述 acceptCharset 服务器可接受的字符集. action 设置或返回表单的 action 属性. enctype 设置或返回表单用来编码内容的 MIME 类型. ...