Java 单向链表学习
Java 单向链表学习
链表等同于动态的数组;可以不同设定固定的空间,根据需要的内容动态的改变链表的占用空间和动态的数组同一形式;链表的使用可以更加便于操作。
链表的基本结构包括:链表工具类和节点类,节点类是工具类的内部类,这样可以便于Link和Node类之间的属性调用和方法使用,也有效的封装了Node类不被外部所使用;
Link类主要负责处理外部类和Node类之间的关系以及链表内容的存储;Node类负责具体的链表结构的操作,比如:添加链表时需要将新的链表放在上一个链表的后面则需要Link调用Node类进行链表结构的定义,同理:大多链表结构的操作都有Node负责具体的操作和定义,而Link类主要负责外部类和Node类的关系。
链表结构中:root负责记录链表首结构的地址,next负责记录当前链表节点的下一个链表节点的地址,data则是记录具体的数据类型的数据信息。
class Link { //链表类(外部可调用的一个工具类) class Node { //节点类,定义该内部类,只可服务于Link类 private String data ; //节点数据 private Node next ; //引用关系(顺序) public Node(String data) { this.data = data ; } public void addNode(Node newNode){ if ( this.next == null){ //下一个节点为空则设置下一个节点 this.next = newNode ; } else { //若节点存在,则向后移 this.next.addNode(newNode) ; } } public boolean containsNode(String data) { //(如果比较的数据是对象,则定义一个对象比较的方法。) if ( data.equals(this.data)) { //对比data return true ; } else { if ( this.next != null ) { // 对比下一个data return this.next.containsNode(data) ; } else { return false ; } } } public String getNode(int index) { //索引查找 // 1 比较index和foot的值是否相等 // 2 将foot的内容自增 1 if ( Link.this.foot ++ == index) { //对比当前节点的foot return this.data ; } else { //下一个节点 return this.next.getNode(index) ; } } public void setNode(int index , String data) { if ( Link.this.foot ++ == index ) { this.data = data ; //内容修改(替换 ) } else { if ( this.next != null ) { this.next.setNode(index,data) ; } } } // 要传递上一个节点以要删除的数据 public void removeNode( Node previous , String data ) { if ( data.equals(this.data)){//数据满足删除条件 previous.next = this.next ; //上一个节点的next指向当前的next(空出当前节点) } else { // 继续匹配查询删除 if(this.next != null) { this.next.removeNode(this , data) ;//this表示当前对象,将this给previous // 因为previous接收的是上一个对象。 } } } public void toArrayNode() { Link.this.retArray[Link.this.foot ++] = this.data ; if ( this.next != null ) { this.next.toArrayNode() ; } } } /* ========================================================================== */ private Node root ; //根节点 private int count = 0 ; //保存元素的个数 private int foot = 0 ; //保存链表的索引编号 private String [] retArray ; //对象数组 public void add(String data) { //数据添加 Node newNode = new Node(data) ; if ( this.root == null ){//无根节点,保存根节点 this.root = newNode ; } else { //向Node调用 this.root.addNode(newNode) ; } this.count ++ ; //每一个保存后数据量自加 1 } public int size() { //判断返回链表数据数量 return this.count ; } public boolean isEmpty() { //判断链表是否为空 return this.count == 0 ; // 根据链表数量判断 } public boolean contains(String data) { //查询数据是否存在 if ( data == null || this.root == null ) { //查找数据为空则false return false ; } return this.root.containsNode(data) ; //不为空则调用Node查找数据; } public String get(int index) { //设置索引目标 index if ( index > this.count ) { return null ; } this.foot = 0 ; //索引归零,表示从左往右查找 return this.root.getNode(index) ; //调用getNode()查找 } public void set(int index , String data) {//修改链表数据内容 if ( data == null || this.root == null ) { return ; } this.foot = 0 ; // 重置foot,便于查找内容 this.root.setNode(index,data) ; //调用Node修改 } /* 如果要删除的是根节点:root指向下一个节点即可 如果删除的不是根节点:删除的前一个节点,下一个节点指向删除的下一个节点 删除数据的形式:当前节点的上一个节点next = 当前节点的next 需要设置一个方法专门处理非根节点的删除(removeNode()方法) */ public void remove(String data) { if ( this.contains(data)) {//contains() 判断数据是否存在 // 判断删除的数据是不是根节点数据 // root是Node类的对象,此处直接访问了Node对象的私有属性 data if ( data.equals(this.root.data)) { this.root = this.root.next ; //空出当前节点(改变根节点) } else { this.root.next.removeNode(this.root , data) ; } this.count -- ; //链表个数减一 } } // 首先开辟一个数组空间,空间 == count public String [] toArray() { //将链表以对象数组形式返回 if (this.root == null ) { return null ; } this.foot = 0 ; //下标控制 this.retArray = new String [this.count] ; //开辟一个数组 this.root.toArrayNode() ; //Node处理 return retArray ; } } public class LinkDemo { //基本程序框架 public static void main(String args[]) { // 测试数据 Link all = new Link(); // 添加数据 all.add("Hello") ; all.add("World") ; all.add("Mirror") ; all.add("2019/4/17") ; all.add( "null" ) ; // 获得链表长度(数据量) System.out.println(all.size()) ; // 判断链表是否为NULL System.out.println(all.isEmpty()) ; // 根据内容查找数据是否存在 System.out.println(all.contains("Hello")) ; System.out.println(all.contains("yang")) ; // 根据索引foot输出链表内容(索引foot是动态的) //某种程度上链表就是动态的数组 System.out.println(all.get(1)) ; //System.out.println(all.get(5)) ; // 修改链表内容 all.set(1,"yang"); System.out.println(all.get(1)) ; //数据删除 all.remove("yang") ; System.out.println(all.contains("yang")) ; System.out.println("====================") ; //对象数组转换 String [] data = all.toArray() ; for ( int x = 0 ; x <= data.length-1 ; x++ ) { System.out.print("\t" + data[x]) ; } } }
链表最好的使用就是横向替代对象数组;可以将存入的数据按照链表存储(顺序方法)。
class Book { private String title ; private double price ; public Book(String title , double price) { this.title = title ; this.price = price ; } public String getInfo() { return "图书名称:" + this.title + ", 价格:" + this.price ; } public boolean compare(Book book) { if ( this == book ) { return true ; } if ( book == null ) { return false ; } if ( this.title.equals(book.title) && this.price == book.price ) { return true ; } return false ; } } class Link { class Node { private Book data ; private Node next ; public Node( Book data ) { this.data = data ; } public void addNode( Node newNode ) { if ( this.next == null ) { this.next = newNode ; } else { this.next.addNode(newNode) ; } } public boolean containsNode( Book data ) { if ( data.compare(this.data) ) { return true ; } else { if ( this.next != null) { return this.next.containsNode(data) ; } else { return false ; } } } public Book getNode(int index) { if ( Link.this.foot ++ == index ) { return this.data ; } else { return this.next.getNode(index) ; } } public void setNode(int index , Book data) { if ( Link.this.foot ++ == index ) { this.data = data ; } else { if ( this.next != null) { this.next.setNode(index,data) ; } } } public void removeNode(Node previous,Book data) { if ( data.compare(this.data)) { previous.next = this.next ; } else { if ( this.next != null) { this.next.removeNode(this,data) ; } } } public void toArrayNode() { Link.this.retArray[Link.this.foot ++] = this.data ; if (this.next != null){ this.next.toArrayNode() ; } } } private Node root ; private int count = 0 ; private int foot = 0 ; private Book [] retArray ; public void add(Book data) { Node newNode = new Node(data) ; if ( root == null ) { root = newNode ; } else { this.root.addNode(newNode) ; } this.count ++ ; } public int size() { return count ; } public boolean isEmpty() { return this.count == 0 ; } public boolean contains( Book data ) { if ( data.compare(root.data) ) { return true ; } else { return this.root.containsNode(data) ; } } public Book get(int index) { if (index > count) { return null; } this.foot = 0 ; return this.root.getNode(index) ; } public void set(int index,Book data) { if ( index > count ) { return ; } this.foot = 0 ; this.root.setNode(index,data) ; } public void remove(Book data) { if ( data.compare(root.data) ) { root = root.next ; } else { this.root.removeNode(this.root,data) ; } count -- ; } public Book [] toArray() { this.foot = 0 ; this.retArray = new Book [this.count] ; this.root.toArrayNode() ; return retArray ; } } public class LinkBook { public static void main(String [] args) { Link all = new Link() ; all.add(new Book("Java开发",89.9)) ; all.add(new Book("JSP开发",78.9)) ; all.add(new Book("Web开发",68.9)) ; System.out.println(all.size()); System.out.println(all.contains(new Book("Java开发",89.9))); Book [] books = all.toArray() ; for ( int x = 0 ; x < books.length ; x ++ ) { System.out.println(books[x].getInfo()) ; } } }
LinkBook【利用链表图书保存】
class Province { //每一个类就相当于数据库中的一个表; private int pid ; private String name ; private Link cities = new Link() ; //一对多 //setter getter 无参构造 略~ public Province(int pid , String name) { this.pid = pid ; this.name = name ; } public Link getCities() { return this.cities ; } public String getInfo() { return "省份编号:" + this.pid + ", 名称:" + this.name ; } } class City { private int cid ; private String name ; private Province province ; //省份对象元素 public City(int cid , String name) { this.cid = cid ; this.name = name ; } public boolean compare(City data) { if ( this == data ) { return true ; } if ( data == null) { return false ; } if ( this.cid == data.cid && this.name.equals(data.name)) { return true ; } return false ; } public void setProvince(Province province) { this.province = province ; } public Province getProvince() { return this.province; } public String getInfo() { return "城市编号:" + this.cid + ", 名称:" + this.name ; } } /* 每一个实例化的对象都是单独的个体的存在,占用的是独立的内存空间 所以每一个实例对象的操作不影响其它实例对象或者类的数据 */ class Link { class Node { private City data ; private Node next ; public Node(City data) { this.data = data; } public void addNode(Node newNode) { if ( this.next == null ) { this.next = newNode ; } else { this.next.addNode(newNode) ; } } public boolean containsNode(City data) { if ( data.compare(this.data)) { return true ; } else { if ( this.next != null ){ return this.next.containsNode(data) ; } else { return false ; } } } public City getNode(int index) { if ( Link.this.foot ++ == index ) { return this.data ; } else { return this.next.getNode(index) ; } } public void setNode(int index , City data) { if ( Link.this.foot ++ == index ) { this.data = data ; } else { this.next.setNode(index , data) ; } } public void removeNode(Node previous , City data) { if ( data.compare(this.data)){ previous.next = this.next ; //空掉当前(this)的节点 } else { if ( this.next != null ) { this.next.removeNode(this,data) ; } } } public void toArrayNode() { Link.this.cityArray[Link.this.foot ++ ] = this.data ; if ( this.next != null ) { this.next.toArrayNode() ; } } } private Node root ; private int count = 0 ; private int foot = 0 ; private City [] cityArray ; public void add(City data) { Node newNode = new Node(data) ; if ( this.root == null ) { this.root = newNode ; } else { this.root.addNode(newNode) ; } this.count ++ ; } public int size() { return this.count ; } public boolean isEmpty() { return count == 0 ; } public boolean contains(City data) { if ( data.compare(this.root.data) ) { //**-- return true ; } else { return this.root.containsNode(data) ; } } public City get(int index) { if ( index > count ){ return null; } this.foot = 0 ; return this.root.getNode(index) ; } public void set(int index , City data) { if ( index > count ){ return ; } this.foot = 0 ; this.root.setNode(index , data) ; } public void remove(City data) { if ( data.compare(this.root.data) ) { this.root = this.root.next ; } this.root.removeNode(this.root , data) ; this.count -- ; } public City [] toArray() { if ( this.root == null ) { return null ; } this.foot = 0 ; this.cityArray= new City[this.count] ; this.root.toArrayNode() ; return cityArray ; } } public class LinkPC { public static void main(String args[]) { // 设置关系数据 Province pro = new Province(1,"江苏省") ; // 声明Province类对象 City c1 = new City(1001,"南京市") ; City c2 = new City(1002,"苏州市") ; City c3 = new City(1003,"宿迁市") ; // 什么多个City类对象 //设置关系 c1.setProvince(pro) ; // 利用City实例对象c1调用setProvince()方法并将pro对象传递 c2.setProvince(pro) ; // 这就是所谓的 "引用传递" c3.setProvince(pro) ; pro.getCities().add(c1) ; pro.getCities().add(c2) ; pro.getCities().add(c3) ; System.out.println(pro.getInfo()); System.out.println(pro.getCities().size()) ; City [] ci = pro.getCities().toArray() ; for ( int x = 0 ; x < ci.length ; x ++ ) { System.out.println(ci[x].getInfo()) ; } } }
利用链表实现省份和城市的映射
Java 单向链表学习的更多相关文章
- JAVA单向链表实现
JAVA单向链表实现 单向链表 链表和数组一样是一种最常用的线性数据结构,两者各有优缺点.数组我们知道是在内存上的一块连续的空间构成,所以其元素访问可以通过下标进行,随机访问速度很快,但数组也有其缺点 ...
- JAVA 单向链表
package com.session.link; /** * 单向链表 */public class LinkedList<T> { private Node head;//指向链表头节 ...
- java 单向链表实现
1 class Node{//Node类 2 private String data; 3 private Node next; 4 public Node(String data){ 5 this. ...
- JAVA单向/双向链表的实现
一.JAVA单向链表的操作(增加节点.查找节点.删除节点) class Link { // 链表类 class Node { // 保存每一个节点,此处为了方便直接定义成内部类 private Str ...
- 单向链表的简单Java实现-sunziren
写在前面,csdn的那篇同名博客就是我写的,我把它现在在这边重新发布,因为我实在不想用csdn了,那边的广告太多了,还有就是那个恶心人的“阅读更多”按钮,惹不起我躲得起. 最近面试的过程中,发现有的公 ...
- C#学习单向链表和接口 IList<T>
C#学习单向链表和接口 IList<T> 作者:乌龙哈里 时间:2015-11-04 平台:Window7 64bit,Visual Studio Community 2015 参考: M ...
- (原创)用Java实现链表结构对象:单向无环链表
转载请注明本文出处:http://www.cnblogs.com/Starshot/p/6918569.html 链表的结构是由一个一个节点组成的,所谓链,就是每个节点的头尾连在一起.而单向链表就是: ...
- Java实现单向链表基本功能
一.前言 最近在回顾数据结构与算法,有部分的算法题用到了栈的思想,说起栈又不得不说链表了.数组和链表都是线性存储结构的基础,栈和队列都是线性存储结构的应用- 本文主要讲解单链表的基础知识点,做一个简单 ...
- [Java算法分析与设计]--单向链表(List)的实现和应用
单向链表与顺序表的区别在于单向链表的底层数据结构是节点块,而顺序表的底层数据结构是数组.节点块中除了保存该节点对应的数据之外,还保存这下一个节点的对象地址.这样整个结构就像一条链子,称之为" ...
随机推荐
- ios7适配--uitableviewcell选中效果
ios7 UITableViewCell selectionStyle won't go back to blue up vote6down votefavorite 2 Xcode 5.0, iOS ...
- gettimeofday()函数的使用方法
1.简介: 在C语言中可以使用函数gettimeofday()函数来得到精确时间.它的精度可以达到微妙,是C标准库的函数. 2.函数原型: #include<sys/time.h> int ...
- 使用Boost库(1)
如何说服你的公司.组织使用Boost库 one of the most highly regarded and expertly designed C++ library projects in th ...
- logback 常用参数配置详解
logback 常用配置详解(二) <appender> <appender>: <appender>是<configuration>的子节点,是负责写 ...
- 以太坊系列之二: 单调时间monotime-以太坊源码学习
在程序中需要测量时间时最好使用monotime.Now()而不是time.Now(),相比之下前者更准确. 来个示例: func main() { var start, elapsed time.Du ...
- LOJ#10065. 「一本通 3.1 例 2」北极通讯网络
题目链接:https://loj.ac/problem/10065 题目描述 原题来自:Waterloo University 2002 北极的某区域共有 nnn 座村庄,每座村庄的坐标用一对整数 ( ...
- 函数返回值string与返回值bool区别------c++程序设计原理与实践(进阶篇)
为什么find_from_addr()和find_subject()如此不同?比如,find_from_addr()返回bool值,而find_subject()返回string.原因在于我们想说明: ...
- [Algorithm]查找
一.查找的算法 1.顺序查找 1 int Search_Seq( SeqList L, ElemType elem ) 2 { 3 L.elem[0] = elem; 4 for ( int i = ...
- MySQL 学习笔记(二):数据库更新、视图和数据控制
基础准备: 在 school 数据库下建立student.course.sc 三个表: create table student( Sno ) primary key, Sname ) unique, ...
- eclipse搭建maven project的spring4 spring mvc mybatis
一,先确定已经安装好了Eclipse Java EE IDE for Web Developers我用的是如下版本 Version: Neon.3 Release (4.6.3)Build id: 2 ...