一、分析

  单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点由元素和指针构成。在Java中,我们可以将单链表定义成一个类,单链表的基本操作即是类的方法,而结点就是一个个实例化的对象,每个对象中都有“元素值”和“下一结点地址”两个属性。在“下一结点地址”属性中存储的是下一个对象的引用,这样,一个个对象连在一起就成为了单链表。

  单链表有以下基本操作:

    1、初始化单链表

    2、销毁单链表

    3、清空单链表

    4、检测单链表是否为空

    5、返回单链表的元素个数

    6、返回单链表中指定位置元素的值

    7、返回单链表中第一个与指定值相同的元素的位置

    8、返回指定元素的直接前驱

    9、返回指定元素的直接后继

    10、向指定位置插入元素

    11、删除指定位置的元素

    12、遍历单链表

  为了方便对单链表进行操作,我们还需要引入一个头结点,头结点中不存储元素值,只存储单链表第一个结点的地址。初始化单链表即创建头结点,而销毁单链表即销毁头结点。

二、实现

1、定义类属性和构造函数

 class InitList{

     private int [] data = new int[1];   //用来存储元素值,之所以用数组而不用整型,是为了用null来表示头结点

     private InitList nextList;       //下一结点地址

     public InitList() {           //创建头结点的构造函数
this.data = null;
this.nextList = null;
} public InitList(int data) {      //创建普通结点的构造函数
this.data[0] = data;
this.nextList = null;
}
}

2、清空单链表

 public void clearList() {
this.nextList = null;         //将头结点的下一结点地址(即单链表的第一个结点的地址)置空,则单链表会因缺少引用而被jvm回收,实现清空
}

3、检测单链表是否为空

 public boolean listEmpty() {
if(this.nextList == null) {      //通过判断头结点的下一结点地址是否为空,即可判断单链表是否为空
return true;
}
return false;
}

4、返回单链表的元素个数

 public int listLength() {

     InitList theList = this.nextList;        //获取头结点的下一结点地址
int i = 0;                //计数器初始化 for (i = 0; theList != null; i++) {      //循环判断结点地址是否为空,如果不为空,则表明存在结点,计数器i加一;如果为空,则表明已到达单链表尾部,退出循环
theList = theList.nextList;       //取下一结点进行判断
}
return i;                     //返回计数器的值
}

5、返回单链表中指定位置元素的值

 public int [] getElem(int site) {

     if(site < 1) {                      //判断输入的位置是否合法
return null;
} InitList theList = this;         //得到头结点的地址 for (int i = 0; i < site; i++) {     //循环读取结点,直到指定的位置
theList = theList.nextList;      //获取下一结点的地址
if(theList == null) {          //如果下一结点地址为空,则表明已经到达单链表末尾,指定的位置超出了单链表的长度
return null;              //未取到元素,返回null
}
}
return theList.data;            //返回指定位置元素值
}

6、返回单链表中第一个与指定值相同的元素的位置

 public int locateElem(int value) {

     InitList theList = this.nextList;

     for(int i = 1; theList != null; i++) {     //如果取得的结点不为空,执行循环
if(theList.data[0] == value) {       //比较结点值与给定的值是否相等
return i;                //相等返回结点位置
}
theList = theList.nextList;        //取下一结点地址
} return 0;                     //未找到则返回零
}

7、返回指定元素的直接前驱

 public int [] priorElem(int value) {

     InitList theList = this.nextList;

     if(theList == null) {                    //如果头结点的下一结点为空,则表明单链表为空,返回null
return null;
} InitList theNextList = this.nextList.nextList;    //获取单链表的第二个结点
int [] ret = new int[this.listLength()];        //创建一个与单链表长度相同的数组,用来存储找到的直接前驱的值
int i = 1;                          //计数器 while (theNextList != null) {               //因为单链表的第一个结点没有直接前驱,因此从第二个结点开始循环
if(theNextList.data[0] == value) {        //如果与给定值相等,则取得其前驱,计数器加一
ret[i] = theList.data[0];
i++;
}
theList = theNextList;               //取下一地址,准备下一循环
theNextList = theNextList.nextList;
} if(i == 1) {                       //i为1表明未取到直接前驱
return null;
} ret[0] = i - 1;                     //将计数器的值存入数组第0位
return ret;
}

8、返回指定元素的直接后继

 public int [] nextElem(int value) {              //与获取直接前驱类似,这里不再赘述

     InitList theList = this.nextList;

     if(theList == null) {
return null;
} InitList theNextList = this.nextList.nextList;
int [] ret = new int[this.listLength()];
int i = 1; while (theNextList != null) {
if(theList.data[0] == value) {
ret[i] = theNextList.data[0];
i++;
}
theList = theNextList;
theNextList = theNextList.nextList;
} if(i == 1) {
return null;
} ret[0] = i - 1;
return ret;
}

9、向指定位置插入元素

 public boolean listInsert(int site,int value) {

     if(site < 1) {                        //判断指定位置是否合法
return false;
}
6
7   InitList list = new InitList(value);
InitList theNextList = this;
InitList theList = null; for(int i = 0; i < site; i++) {             //循环读取到指定位置
theList = theNextList;
if(theList == null) {                //如果为空,表示已到单链表末尾,返回false
return false;
}
theNextList = theNextList.nextList;
} list.nextList = theNextList;                //将新结点插入指定位置中
theList.nextList = list;
return true;
}

10、删除指定位置的元素

 public boolean listDelete(int site) {

     InitList theList = this;
InitList theNextList = this.nextList; if(site < 1 || theNextList == null) {       //判断指定位置是否合法和单链表是否为空
return false;
}else if(site == 1) {                  //如果要删除的是第一个结点,则直接删除
theList.nextList = theNextList.nextList;
return true;
} for(int i = 1; i < site; i++) {            //循环读取到指定位置
theNextList = theNextList.nextList;
if(theNextList == null) {
return false;
}
theList = theList.nextList;
} theList.nextList = theNextList.nextList;      //删除指定位置的结点
return true;
}

11、遍历单链表

 public String traverseList() {          //这里通过输出单链表来表示遍历

     InitList theList = this.nextList;
String s = "";                //用来存储单链表的值 while(theList != null) {           //循环获取结点值
s += theList.data[0] + "、";
theList = theList.nextList;
} if(s.length() == 0) {            //如未获取到值,直接返回s
return s;
} return s.substring(0,s.length() - 1);  //去除最后的顿号后返回
}

三、小结

  以上就是单链表用Java的实现,由于只定义了整数的数组,因此只能操作整数数据,但单链表的基本思想都已实现。

四、纠正

  隔了一段时间又回来看代码,猛地发现这段代码其实还不够完善。(⊙x⊙;)

  将单链表的基本操作定义成了InitList类的方法,实例化结点时,会使每个结点都拥有这些方法,然而其实只有头结点需要这些方法,其他结点都不需要。

  因此可以将InitList类定义成头节点类,而其他节点定义成头节点的内部类,这样,就只有头节点可以操作其他节点。

  由于要修改的地方太多,这里我就不修改了,放在这里提醒自己。(就是因为懒……(><))

数据结构——Java实现单链表的更多相关文章

  1. Java实现单链表的各种操作

    Java实现单链表的各种操作 主要内容:1.单链表的基本操作 2.删除重复数据 3.找到倒数第k个元素   4.实现链表的反转   5.从尾到头输出链表 6.找到中间节点 7.检测链表是否有环 8.在 ...

  2. java实现单链表的增删功能

    JAVA 实现单链表的增删功能 package linked; class LinkedTable{ } public class LinkedTableTest { public static vo ...

  3. 使用java实现单链表(转载自:https://www.cnblogs.com/zhongyimeng/p/9945332.html)

    使用java实现单链表----(java中的引用就是指针)转载自:https://www.cnblogs.com/zhongyimeng/p/9945332.html ? 1 2 3 4 5 6 7 ...

  4. java实现单链表、栈、队列三种数据结构

    一.单链表 1.在我们数据结构中,单链表非常重要.它里面的数据元素是以结点为单位,每个结点是由数据元素的数据和下一个结点的地址组成,在java集合框架里面 LinkedList.HashMap(数组加 ...

  5. java实现单链表常见操作

    一.概述: 本文主要总结单链表常见操作的实现,包括链表结点添加.删除:链表正向遍历和反向遍历.链表排序.判断链表是否有环.是否相交.获取某一结点等. 二.概念: 链表: 一种重要的数据结构,HashM ...

  6. js数据结构与算法--单链表的实现与应用思考

    链表是动态的数据结构,它的每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成. 现实中,有一些链表的例子. 第一个就是寻宝的游戏.你有一条线索,这条线索是指向寻找下一条线 ...

  7. Java实现单链表反转操作

    单链表是一种常见的数据结构,由一个个节点通过指针方式连接而成,每个节点由两部分组成:一是数据域,用于存储节点数据.二是指针域,用于存储下一个节点的地址.在Java中定义如下: public class ...

  8. 用Java实现单链表的基本操作

    笔试题中经常遇到单链表的考题,下面用java总结一下单链表的基本操作,包括添加删除节点,以及链表转置. package mars; //单链表添加,删除节点 public class ListNode ...

  9. Java实现单链表的快速排序和归并排序

    本文描述了LeetCode 148题 sort-list 的解法. 题目描述如下: Sort a linked list in O(n log n) time using constant space ...

随机推荐

  1. java日志文件用法总结

    1.基本概念 日志门面(接口):commons logging ; slf4j ; 日志具体实现:log4j ; logback(Spring 系列在使用) ; log4j2(添加了异步logger的 ...

  2. MIP技术进展月报第2期: 数据绑定,异步脚本加速

    一. 功能更新 1. mip-bind 上线,实现复杂交互 MIP bind 双向绑定机制和组件上线,提供双向绑定的特性:能够允许页面实现数据驱动功能,开发者可以在任意场景修改数据,并驱动页面元素变动 ...

  3. 【STM32H7教程】第8章 STM32H7的终极调试组件Event Recorder

    完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第8章   STM32H7的终极调试组件Event Re ...

  4. Adobe Photoshop CC 2019 for Mac v20.0.4 中文版安装教程

    全新Adobe Photoshop CC 2019 mac特别版终于上线了,简称ps cc 2019,Adobe Photoshop CC 2019 for Mac v20.0.4 中文版安装教程分享 ...

  5. 微服务架构 - 离线部署k8s平台并部署测试实例

    一般在公司部署或者真实环境部署k8s平台,很有可能是内网环境,也即意味着是无法连接互联网的环境,这时就需要离线部署k8s平台.在此整理离线部署k8s的步骤,分享给大家,有什么不足之处,欢迎指正. 1. ...

  6. [翻译 EF Core in Action 1.10] 应该在项目中使用EF Core吗?

    Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...

  7. Java - 静态代理详讲

    Java - 静态代理详讲 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 写在前面:*此章内容比较抽象,所以需要结合实际操作进行讲解*                   *需要有 ...

  8. 用animation的steps属性制作帧动画

    昨天火急火燎地接到一个任务,说是要做一个掷骰子的游戏,关于掷骰子期间的过渡动画,我本来是想用css 3d制作一个立体的骰子,然后叫UI给6张平面图贴上去.再用translate3d来操作.然而UI考虑 ...

  9. Android之应用市场排行榜、上架、首发

    文章大纲 一.应用市场排行榜介绍二.应用市场上架介绍三.应用市场首发介绍四.参考文档   一.应用市场排行榜介绍   iiMedia Research(艾媒咨询)权威发布<2017-2018中国 ...

  10. 2018-12-25 VS Code英汉词典v0.0.8: 批量翻译文件部分命名

    续前文: VS Code英汉词典进化效果演示: 翻译文件所有命名 vscode"英汉词典"插件地址: 官方链接 现在实现的效果比之前的演示差很多, 因为executeDocumen ...