Java链表的基本使用

Java链表的基本使用得到的

大家好,又见面了,我是你们的朋友全栈君。

链表是一种根据元素节点逻辑关系排列起来的一种数据结构。利用链表可以保存多个数据,这一点类似于数组的概念,但是数组本身有一个缺点—— 数组的长度固定,不可改变,在长度固定的情况下首选的肯定是数组,但是在现实的开发之中往往要保存的内容长度是不确定的,那么此时就可以利用链表这样的结构来代替数组的使用。

链表是一种最为简单的数据结构,它的主要目的是依靠引用关系来实现多个数据的保存。

下面是定义一个简单的类用来保存节点关系,并将所有节点链接起来。

例子1:

//每一个链表实际上就是由多个节点组成的
class Node { 
       
	private String data; //用于保存数据
	private Node next;   //用于保存下一个节点
	
	public Node(String data){ 
     //每一个Node类对象都必须保存有数据
		  this.data = data ;
	}
	
	public void setNext(Node next){ 
   
		  this.next = next ;
	}
	
	public Node getNext(){ 
   
		  return this.next ;
	}
	
	public String getData(){ 
   
		  return this.data ;
	}
}

public class LinkedList { 
   
	 
	public static void main(String[] args) { 
   
		
		//第一步:准备数据
		Node root = new Node("火车头") ;
		Node n1 = new Node("车厢A") ;
		Node n2 = new Node("车厢B") ;

		// 链接节点
		root.setNext(n1);
		n1.setNext(n2);
		
		//第二步:取出所有数据
		Node currentNode = root ;  //从当前根节点开始读取
		while( currentNode !=  null){ 
   
			System.out.println(currentNode.getData()) ;
			//将下一个节点设置为当前节点s
			currentNode = currentNode.getNext() ;
		}
 }
}

运行:

火车头
车厢A
车厢B

例子2:
在进行链表操作的时候,首先需要的是一个根节点(第一个节点即为根节点),之后每一个节点的引用都保存在上一节点的next属性之中,而在进行输出的时候也应该按照节点的先后顺序,一个一个取得每一个节点所包装的数据。

public class LinkedList { 

public static void main(String[] args) { 

Link link = new Link() ;
link.add("hello");   //增加节点
link.add("world");
link.add("wwww");
link.print();     //打印数据 
}	
}
//每一个链表实际上就是由多个节点组成的
class Node { 
 
private String data; // 用于保存数据
private Node next; // 用于保存下一个节点
public Node(String data) { 
  // 每一个Node类对象都必须保存有响应的数据
this.data = data;
}
public void setNext(Node next) { 

this.next = next;
}
public Node getNext() { 

return this.next;
}
public String getData() { 

return this.data;
}
// 实现节点的添加:
// 第一次调用(Link):this代表Link.root
// 第二次调用(Node):this代表Link.root.next
// 第三次调用(Node):this代表Link.root.next.next
public void addNode(Node oldNode,Node newNode) { 
	
System.out.println("now:"+oldNode);
if (this.next == null) { 
   // 保存新节点
this.next = newNode; 
} else { 
                 // 当前节点后面还有节点 
this.next.addNode(this.next,newNode);  // 当前节点的下一个节点继续保存,这里采用的是递归添加节点
}
System.out.println(oldNode+"=>"+this.next);
}
// 第一次调用(Link):this代表Link.root
// 第二次调用(Node):this代表Link.root.next
// 第三次调用(Node):this代表Link.root.next.next
public void printNode() { 

System.out.println("pp:"+this.data);// 输出当前数据
if (this.next != null) { 
      // 如果还有下一个节点,输出下一节点
this.next.printNode();   // 递归打印节点,注意这里的this.next中的this指代
}
}
}
// 链表增加节点,输出节点数据
class Link { 

private Node root; //新建根节点
public void add (String data){ 

Node newNode = new Node(data);  //链表中新增节点类对象 
if(this.root == null ){ 
         // 如果链表还没有任何节点,就添加第一个节点作为根节点
this.root = newNode;   
System.out.println("root:"+this.root);
}else{ 
 
System.out.println("new:"+newNode);
this.root.addNode(this.root,newNode);  //从根节点节点新链接一个节点
}
}
//输出当前节点数据
public void print(){ 

if( this.root != null ){ 
  
this.root.printNode();
}
}
}

运行:

root:test.Node@7852e922
new:test.Node@4e25154f
now:test.Node@7852e922
test.Node@7852e922=>test.Node@4e25154f
new:test.Node@70dea4e
now:test.Node@7852e922
now:test.Node@4e25154f
test.Node@4e25154f=>test.Node@70dea4e
test.Node@7852e922=>test.Node@4e25154f
pp:hello
pp:world
pp:wwww

例子3:

关键是构造一个类,里面包含一个指向下一个元素的对象(指向下一个元素的指针)

public class LinkedList{ 

public static void main(String[] args){ 

MyLinkedList linkedList = new MyLinkedList();
System.out.println("-------start-------");
System.out.println("ll:"+linkedList.listEm());
for (int i=0;i<5;i++){ 
   //新建链表
linkedList.add(i+1);
}
System.out.println("mm:"+linkedList.listEm());  //打印链表
for(int i=0;i<5;i++){ 
  //删除链表
System.out.println("remove:"+linkedList.remove());
}
System.out.println("kk:"+linkedList.listEm());
System.out.println("-------end-------");
}
}
class Node<T> { 

Node<T> next;
T element;
public Node( Node<T> next, T element){ 

this.next = next;
this.element = element;
}
}
class MyLinkedList<T> { 

private int size ;	
Node<T> last;     //指向list中最后一个元素 
Node<T> first;    //指向list中第一个元素 
Node<T> currRead; //指向当前读取的元素 
// 默认构造函数
public MyLinkedList(){ 
   
this.size = 0;
this.last =  new Node(null,-1);
this.first = last;
this.currRead = first;
}
//往链表中添加数据(队尾添加数据) 
public void add(T element){ 

Node<T> newNode = new Node<T>(null,element);
this.last.next = newNode;
this.last = newNode;  // 引用平移
if(size == 0){ 

this.first = newNode;
}
size ++;
}
//移除链表中的数据(队头移除)
public T remove(){ 

if(size == 0){ 

System.out.println("empty list ");
this.currRead = this.first;
return null;
}
T result = this.first.element;
this.first = this.first.next;
this.currRead = this.first;
size--;
return result;
}
//获取队列中的元素
public T get(){ 

if(this.currRead.next == null){ 

this.setReadAgain();
return this.currRead.element;
}
T result = this.currRead.element;
this.currRead = this.currRead.next;
return result;
}
//再次从头开始读取数据
public void setReadAgain() { 

this.currRead = this.first;
}
public String listEm(){ 

StringBuilder sb = new StringBuilder();
for(int i=0;i<size;i++){ 

T ele = this.get();
sb.append(this.currRead.element + "-->");
}
return sb.toString();
}
//获取队列大小
public int getSize(){ 

return this.size;
}
}

运行:

-------start-------
ll:
mm:1-->2-->3-->4-->5-->
remove:1
remove:2
remove:3
remove:4
remove:5
kk:
-------end-------

例四:

public class LinkedList { 

public static void main(String [] args){ 
 
Link l=new Link();  
mytype[] la;  
mytype dsome=new mytype("韩敏","dsome",21);  
mytype shao=new mytype("邵晓","john",45);  
mytype hua=new mytype("华晓风","jam",46);  
mytype duo=new mytype("余小风","duo",1000);  
mytype wang=new mytype("王秋","jack",21);  
mytype shi=new mytype("韩寒","bob",3000);  
mytype yu=new mytype("于冬","keven",30); 
l.add(dsome);//测试增加节点 
l.add(shao);  
l.add(hua);  
l.add(wang);  
l.add(shi);  
l.add(duo);  
l.add(yu);  
System.out.println("链表长度:"+l.length());//链表长度
la=l.toArray();  
for(int i=0;i<la.length;i++){ 
  
System.out.println(la[i].getInfo());  
}  
System.out.println("是否包含余小风:"+l.contains(duo)+"\n");  
System.out.println("删除余小风后\n");  
l.remove(duo);  
la=l.toArray();  
for(int i=0;i<la.length;i++){ 
    //转化为数组之后输出 
System.out.println(la[i].getInfo());  
}    
System.out.println("\n利用索引方法输出全部数据");  
for(int i=0;i<l.length();i++){ 
  
System.out.println(l.get(i).getInfo());  
}    
System.out.println("是否包含余小风:"+l.contains(duo)+"\n");  
l.clean();  
System.out.println("执行清空操作后链表长度: "+l.length()+"\t是否为空链表:"+l.isEmpty());  
}
}
class Link { 

//内部类 
private class Node{ 
   
private Node next;  
private mytype data;  
public Node(mytype data){ 
  
this.data=data;  
}  
public void addNode(Node newNode){ 
  //增加节点 
if(this.next==null){ 
  
this.next=newNode;   // 指向新的节点
}else{ 
  
this.next.addNode(newNode);    // 递归调用是为了让next引用指向新的节点
}  
}  
public mytype getNode(int index){ 
//按照角标返回数据 
if(index==Link.this.foot++){ 
  
return this.data;  
}else{ 
  
return this.next.getNode(index);  
}  
}  
public boolean iscontain(mytype data){ 
//判断是否含有该数据 
if(this.data.equals(data)){ 
  
return true;  
}else{ 
  
if(this.next!=null){ 
  
return this.next.iscontain(data);  
}else{ 
  
return false;  
}  
}  
}  
public void removeNode(Node previous,mytype data){ 
  //删除节点 
if(this.data.equals(data)){ 
    //this:下一个节点B
previous.next=this.next;    // this.next:节点B的下一个节点C,previous:节点A
}else{ 
  
this.next.removeNode(this,data);  //注意这里的this.next和this的区别:this.next是下一个节点B,this是当前节点A
}  
}  
public void toArrayNode(){ 
  //转化数组 
Link.this.Larray[Link.this.foot ++]=this.data;  //每个节点的数据添加到一个mytype []中
if(this.next!=null){ 
  
this.next.toArrayNode();  
}  
}   
}
//内部类定义完毕 
private Node root;  
private int count=0;  
private int foot;  
private mytype [] Larray;
public void add(mytype data){ 
   //增加节点 
if(data==null){ 
  
System.out.print("增加数据失败,数据为空");//测试用 
return;  
}  
Node newNode=new Node(data);  //新建节点
if(this.root==null){ 
  
this.root=newNode;  
this.count++;  
}else{ 
  
this.root.addNode(newNode);  
this.count++;  
}  
}  
public int length(){ 
//链表长度 
return this.count;  
}  
public boolean isEmpty(){ 
//是否为空链表 
if(this.count==0)return true;  
else return false;  
}  
public void clean(){ 
//清空链表 
this.root=null;  
this.count=0;  
}  
public mytype get(int index){ 
//索引返回节点所存的数据 
if(index>=this.count||index<0){ 
  
System.out.print("越界错误");//测试用 
return null;  
}else{ 
  
this.foot=0;  
return this.root.getNode(index);  
}  
}  
public boolean contains(mytype data){ 
  //判断链表数据是否含data 
if(data==null)  
return false;
else
return this.root.iscontain(data);  
}  
public void remove(mytype data){ 
  //删除指定数据节点 
if(this.contains(data)){ 
  
if(this.root.data.equals(data)){ 
  
this.root=this.root.next;  
this.count--;     
}  
else{ 
  
this.count--;  
this.root.next.removeNode(root,data);  
}  
}else{ 
  
System.out.print("删除错误");//测试用 
}  
}  
public mytype[] toArray(){ 
  //把链表转化成对象数组 
if(this.count==0){ 
  
return null;  
}  
this.foot=0;  
this.Larray=new mytype [this.count];  
this.root.toArrayNode();  
return this.Larray;         
}         
}
class mytype { 

private String name;  
private String people;  
private int age;
public mytype(String name,String people,int age){ 
//链表中的数据(可自定义) 
this.name=name;  
this.people=people;  
this.age=age;  
}  
public boolean equals(mytype data){ 
//判断数据是否相同 
if(this==data){ 
  
return true;  
}  
if(data==null){ 
  
return false;  
}  
if(this.name.equals(data.name)&&this.people.equals(data.people)&&this.age==data.age){ 
  
return true;  
}else{ 
  
return false;  
}  
}
public String getName() { 

return name;
}
public void setName(String name) { 

this.name = name;
}
public String getPeople() { 

return people;
}
public void setPeople(String people) { 

this.people = people;
}
public int getAge() { 

return age;
}
public void setAge(int age) { 

this.age = age;
} 
public String getInfo(){ 
  
return "名字 :"+this.name+"\n"+  
"人物 :"+this.people+"\n"+  
"年龄 :"+this.age;  
}     
}

运行:

链表长度:7
名字 :韩敏
人物 :dsome
年龄 :21
名字 :邵晓
人物 :john
年龄 :45
名字 :华晓风
人物 :jam
年龄 :46
名字 :王秋
人物 :jack
年龄 :21
名字 :韩寒
人物 :bob
年龄 :3000
名字 :余小风
人物 :duo
年龄 :1000
名字 :于冬
人物 :keven
年龄 :30
是否包含余小风:true
删除多余后
名字 :韩敏
人物 :dsome
年龄 :21
名字 :邵晓
人物 :john
年龄 :45
名字 :华晓风
人物 :jam
年龄 :46
名字 :王秋
人物 :jack
年龄 :21
名字 :韩寒
人物 :bob
年龄 :3000
名字 :于冬
人物 :keven
年龄 :30
利用索引方法输出全部数据
名字 :韩敏
人物 :dsome
年龄 :21
名字 :邵晓
人物 :john
年龄 :45
名字 :华晓风
人物 :jam
年龄 :46
名字 :王秋
人物 :jack
年龄 :21
名字 :韩寒
人物 :bob
年龄 :3000
名字 :于冬
人物 :keven
年龄 :30
是否包含多余:false
执行清空操作后链表长度: 0	是否为空链表:true

参考:
https://blog.csdn.net/qq_37199582/article/details/79244657
https://blog.csdn.net/google_huchun/article/details/52824024

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/135767.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • idm下载百度网盘有限制 提示403错误 下载显示没有权限404,最新的解决办法教程

    idm下载百度网盘有限制 提示403错误 下载显示没有权限404,最新的解决办法教程近期idm下载百度网盘速度在20k/s-50k/s左右,针对这个问题,在2020年10月25日,百度网盘直链提取作者更改了下载接口,速度又能达到nm/s了。user-agent需要更改为netdisk没有了下载数的限制,可以尽可能把下载线程拉高以提高下载速度,服务器可以不填写了,支持同时下载多个文件,不会再提示403错误了以下为测试截图我用的是校园网,每秒接近三M已经很快了,一百多M的视频几秒钟就完事儿了,还是很赞的!如果大家喜欢今天的推文的话,希望大家支持一下小编,点个在看啥的,谢谢大家!今

  • Python爬虫框架Scrapy获得定向打击批量招聘信息

    Python爬虫框架Scrapy获得定向打击批量招聘信息

  • leetcode 回文数_字符串反转java

    leetcode 回文数_字符串反转java原题链接请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。函数 myAtoi(string s) 的算法如下:读入字符串并丢弃无用的前导空格检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。将前面步骤读入的这些数字转换为整数(即,“1

  • 线性代数,行列式(加边法求行列式例题)

    一、二阶和三阶行列式1.二阶行列式PS:只适用于二元线性方程;2.三阶行列式 二、全排列及其逆序数1.全排列把n个不同的元素排成一列,叫做这n个元素的全排列;2.逆序数对于n个不同的元素,先规定各元素之间有一个标准次序,于是在这n个元素的任一排列中,当某两个元素的先后次序与标准次序不同时,就说有一个一个逆序,一个排列中所有逆序的总数叫做这个排列的逆序数。…

  • 学习记录03(网页挂马)

    学习记录03(网页挂马)网页挂马将木马程序上传到网站,使用木马生成器生成一个网马,放到网页空间,在添加代码使木马在网页打开时运行常见的几种方式将木马伪装成页面元素,木马被浏览器自动加载到本地利用脚本运行的漏洞下载木马利用脚本运行的漏洞释放隐含在网页脚本中的木马将木马伪装成缺失的组件。或和缺失的组件绑在一起(flash播放插件等)通过脚本运行调用某些com组件,利用其漏洞下载木马在渲染页面内容的过程中…

  • eclipse乱码解决方法

    eclipse乱码解决方法eclipse之所以会出现乱码问题是因为eclipse编辑器选择的编码规则是可变的。一般默认都是UTF-8或者GBK,当从外部导入的一个工程时,如果该工程的编码方式与eclipse中设置的编码方式不同,就会产生中文的乱码问题,这其中还有几种情况。如果导入的整个工程的编码方式与eclipse的编码方式有冲突,那么这个工程里所有的中文都是乱码;如果所有工程的编码方式与eclipse工作空间的

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号