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)的实现和应用
单向链表与顺序表的区别在于单向链表的底层数据结构是节点块,而顺序表的底层数据结构是数组.节点块中除了保存该节点对应的数据之外,还保存这下一个节点的对象地址.这样整个结构就像一条链子,称之为" ...
随机推荐
- css总结11:css的overflow问题
1 排版时经常遇到块级元素内容overflow,怎么妥当处理是一个关键. overflow的常用属性: 代码: <!DOCTYPE html><html lang="en ...
- Slf4j MDC 使用和 基于 Logback 的实现分析
前言 如今,在 Java 开发中,日志的打印输出是必不可少的, 关于 有了日志之后,我们就可以追踪各种线上问题.但是,在分布式系统中,各种无关日志穿行其中,导致我们可能无法直接定位整个操作流程.因此 ...
- web.xml配置及详解
1.web.xml 是网络程序中的一个很重要的配置文件. 2.XML基础标准是为XML的进一步实用化制定的标准,它规定了采用XML制定标准时的一些公用特征.方法或规则.XML Schema描述了更加严 ...
- mysql 复制(主从复制)
一.概述 让一台服务器的数据与其他服务器数据保持同步.一台主库的数据可以同步到多台备库上,而备库本身也可以配置成其他服务器的主库. 主要应用: 1) 数据分布 2) 负载均衡 3) 伪备份.在备份基础 ...
- 钩子(hook)编程
一.钩子介绍 1.1钩子的实现机制 钩子英文名叫Hook,是一种截获windows系统中某应用程序或者所有进程的消息的一种技术.下图是windows应用程序传递消息的过程: 如在键盘中按下一键,操作系 ...
- Mysql数据库自动定时备份软件推荐--MySqlBackupFTP(免费,亲测可用,附使用图示)
MySqlBackupFTP是一款Mysql数据库自动定时备份软件,免费版本就基本上可以满足我们的需求,不需要什么破解版,可直接官网下载安装使用. 先看结果(日志): 软件界面: 可以设定计划任务,每 ...
- requests模块处理cookie,代理ip,基于线程池数据爬取
引入 有些时候,我们在使用爬虫程序去爬取一些用户相关信息的数据(爬取张三“人人网”个人主页数据)时,如果使用之前requests模块常规操作时,往往达不到我们想要的目的. 一.基于requests模块 ...
- oracle导出clob 工具
oracle导出clob 等大字段,用pl/sql 等无法导出,除了备份数据库,但是一般数据库中正式环境数据和开发环境中数据不一定完全一致或者合适导出,即使仅仅导出导入一个表,有时候也不方便或者业务上 ...
- python获取函数参数默认值的两种方法
1.使用函数的__defaults__魔术方法 demo: # coding=utf-8 def f(a,b,c=1): pass f.__defaults__ 输出结果: (1,) 2.使用insp ...
- 斐讯 N1 刷 Armbian 5.64
前言 N1 天天链是斐讯出的一款挖矿产品,虽然已经翻车,但是本身硬件配置还是很不错的,晶晨 S905D 主控,蓝牙 4.1,双频 WiFi,2G + 8G,USB2.0,HDMI.而一个只要不到 80 ...