三十.链表的定义与使用

链表实现简介

链表是一种非顺序的动态的对象数组,它可以实现若干个对象的储存。
数据之间的逻辑顺序是靠链表中的指针来实现的。而链表本身由结点组成、结点可以在运动时动态生成;

链表的存储结构

一般的对象数组是通过下标来进行控制的,这样也就有一个缺点,那就是长度是固定的。这样的话就会有个限制,而我们使用数组不能超过这个限制。那么要实现数据的动态维护,难度太高了。所以现在对于一成不变的数据就用对象数组,对于可能随时变化的数据就必须实现一个可以动态扩充的对象数组我们就使用链表。

所谓的链表实质性的本质是利用引用的逻辑关系来实现类似于数组的数据处理操作,以一种保存“多”方数据的形式,实现数组类似的功能。

如果要实现链表的处理,那么需要有一个公共的结构,这个结构可以实现数据的保存以及下一个连接的指向。为了描述这样的逻辑,可以把每一个存储理解为一个节点,所以此时应该准备出一个节点类,这个节点类里面可以保存各种数据类型的数据。
在这里插入图片描述

public class Node<E> {
	
	private E data;				//存储数据
	private Node next;			//存储下一个节点
	
	//设置数据与节点
	public Node(E data){
		this.data = data;
	}
	
	public void setNode(Node next){
		this.next = next;
	}
	
	//返回数据与节点
	public E getData(){
		return this.data;
	}
	
	public Node getNode(){
		return this.next;
	}


}
//测试类
public class Test{
	public static void main(String[] args) 
	{
		Node<String> n1 = new Node<String>("火车头");
		Node<String> n2 = new Node<String>("车厢一");
		Node<String> n3 = new Node<String>("车厢二");
		Node<String> n4 = new Node<String>("车厢三");
		Node<String> n5 = new Node<String>("车厢四");
		//设置下一个节点next
		n1.setNode(n2);
		n2.setNode(n3);
		n3.setNode(n4);
		n4.setNode(n5);
 
		//调用print方法
		print(n1);
	}
 
	public static void print(Node<?> node){
		if(node != null){	//有节点
			System.out.println(node.getData());
			print(node.getNode());//递归调用
		}
	}
}

输出结果:

火车头
车厢一
车厢二
车厢三
车厢四

基本结构

@SuppressWarnings("all")
public class LinkList<E> implements ILink<E> {
    
	private class Node<E>{
		private E data; 		//存储的数据
		private Node next;		//下一个节点
		
		public Node(E data){	//构造方法,在实例化的时候存储数据
			this.data = data;
		}
	}
	
	private Node root;			//作为链表的头

	
	//-----------------以下是ILink方法---------------------

	//遍历
	@Override
	public void printList() {
		Node<E> next = this.root;		//获取第一个数据
		
		while (true) {					//无限循环
			if (next == null) {			//为null
				break;					//跳出循环
			}
			
			System.out.println(next.data);	//输出数据
			next = next.next;			//获取下一个节点
		}
	}
}

interface ILink<E>{
	public void printList();		//遍历
}

数据增加

这里面为了避免数据问题就使用了泛型,同时也设计了一个标准的链表接口

package amazon;

@SuppressWarnings("all")
public class LinkList<E> implements ILink<E> {
    
	private class Node<E>{
		private E data; 		//存储的数据
		private Node next;		//下一个节点
		
		public Node(E data){	//构造方法,在实例化的时候存储数据
			this.data = data;
		}
		
		public void addNode(Node next){	//保存新的数据
			if (this.next == null) {	//如果是节点
				this.next = next;		//则添加进去
			}else{	//如果有了节点
				this.next.addNode(next);//继续往下查空节点
			}
		}
	}
	
	private Node root;			//作为链表的头

	
	//-----------------以下是ILink方法---------------------
	//添加
	@Override
	public void add(E data) {
		if (data == null) {		//保存数据为null
			return;				//结束方法直接返回
		}
		
		Node<E> next = new Node<E>(data);		//创建一个新的节点
		if (this.root == null) {		//没有根节点
			this.root = next;			//第一个节点做为根节点
		}else{	//根节点存在
			this.root.addNode(next);	//当有了根节点,就往下一个节点添加
		}
		
	}

	
	//遍历
	@Override
	public void printList() {
		Node<E> next = this.root;		//获取第一个数据
		
		while (true) {					//无限循环
			if (next == null) {			//为null
				break;					//跳出循环
			}
			
			System.out.println(next.data);	//输出数据
			next = next.next;			//获取下一个节点
		}
	}
}

interface ILink<E>{
	
	public void add(E data);		//添加
	
	public void printList();		//遍历
}
public static void main(String[] args) {
		
		ILink<String> all = new LinkList<String>();
		all.add("Hello");
		all.add("World");
		all.add("ddddd");
		
		all.printList();
		
	}

输出结果:

Hello
World
ddddd

获取集合个数

统计链表的数量,只需要在LinkList中创建一个私有的方法用来保存个数就行了,在添加和删除的方法里面分别用++和–在进行记录。

package amazon;

@SuppressWarnings("all")
public class LinkList<E> implements ILink<E> {
    
	private class Node<E>{
		private E data; 		//存储的数据
		private Node next;		//下一个节点
		
		public Node(E data){	//构造方法,在实例化的时候存储数据
			this.data = data;
		}
		
		public void addNode(Node next){	//保存新的数据
			if (this.next == null) {
				this.next = next;
			}else{
				this.next.addNode(next);
			}
		}
	}
	//-----------------以下是LinkList的成员属性--------------
	private Node root;			//作为链表的根节点
	private int count;			//作为链表的长度/数量
	
	//-----------------以下是ILink方法---------------------
	//添加
	@Override
	public void add(E data) {
		if (data == null) {		//保存数据为null
			return;				//结束方法直接返回
		}
		
		Node<E> next = new Node<E>(data);		//创建一个新的节点
		if (this.root == null) {		//没有根节点
			this.root = next;			//第一个节点做为根节点
		}else{	//根节点存在
			this.root.addNode(next);	//当有了根节点,就往下一个节点添加
		}
		
		this.count++;		//每添加一个对象都会加一
	}
	
	@Override
	public int size(){
		return this.count;
	}
	
	//遍历
	@Override
	public void printList() {
		Node<E> next = this.root;		//获取第一个数据
		
		while (true) {					//无限循环
			if (next == null) {			//为null
				break;					//跳出循环
			}
			
			System.out.println(next.data);	//输出数据
			next = next.next;			//获取下一个节点
		}
	}
}

interface ILink<E>{
	
	public void add(E data);		//添加
	public int size();				//长度
	
	public void printList();		//遍历
}
public static void main(String[] args) {
		
		ILink<String> all = new LinkList<String>();
		all.add("Hello");
		all.add("World");
		all.add("ddddd");
		
		System.out.println(all.size());
		
	}

输出结果:

3

空集合判断

链表里面可以保存有若干个数据,如果现在链表还没有保存数据,则就表示是一个空集合,应该提供有一个空的判断

package amazon;

@SuppressWarnings("all")
public class LinkList<E> implements ILink<E> {
    
	private class Node<E>{
		private E data; 		//存储的数据
		private Node next;		//下一个节点
		
		public Node(E data){	//构造方法,在实例化的时候存储数据
			this.data = data;
		}
		
		public void addNode(Node next){	//保存新的数据
			if (this.next == null) {
				this.next = next;
			}else{
				this.next.addNode(next);
			}
		}
	}
	//-----------------以下是LinkList的成员属性--------------
	private Node root;			//作为链表的根节点
	private int count;			//作为链表的长度/数量
	
	//-----------------以下是ILink方法---------------------
	//添加
	@Override
	public void add(E data) {
		if (data == null) {		//保存数据为null
			return;				//结束方法直接返回
		}
		
		Node<E> next = new Node<E>(data);		//创建一个新的节点
		if (this.root == null) {		//没有根节点
			this.root = next;			//第一个节点做为根节点
		}else{	//根节点存在
			this.root.addNode(next);	//当有了根节点,就往下一个节点添加
		}
		
		this.count++;		//每添加一个对象都会加一
	}
	
	//长度
	@Override
	public int size(){
		return this.count;
	}
	
	//判断是否为空
	@Override
	public boolean isEmpty() {
		return this.count == 0;		//true为空,false非空
	}
	
	//遍历
	@Override
	public void printList() {
		Node<E> next = this.root;		//获取第一个数据
		
		while (true) {					//无限循环
			if (next == null) {			//为null
				break;					//跳出循环
			}
			
			System.out.println(next.data);	//输出数据
			next = next.next;			//获取下一个节点
		}
	}

}

interface ILink<E>{
	
	public void add(E data);		//添加
	public int size();				//长度
	public boolean isEmpty();		//判断链表是否为空
	
	public void printList();		//遍历
}
public static void main(String[] args) {
		
		ILink<String> all = new LinkList<String>();
		all.add("Hello");
		all.add("World");
		
		System.out.println(all.isEmpty());
		
	}

输出结果:

false

返回集合数据

链表本身就属于一个动态对象数组,那么既然是一个对象数组,就应该可以把所有的数据以数组的形式返回来,这时可以定义一个toArray()方法,但是这个时候只能返回Object型的数组。

package amazon;

@SuppressWarnings("all")
public class LinkList<E> implements ILink<E> {
    
	private class Node<E>{
		private E data; 		//存储的数据
		private Node next;		//下一个节点
		
		public Node(E data){	//构造方法,在实例化的时候存储数据
			this.data = data;
		}
		
		public void addNode(Node next){	//保存新的数据
			if (this.next == null) {
				this.next = next;
			}else{
				this.next.addNode(next);
			}
		}
		
		public void toArrayNode(){
			//从内部类获取外部类的私有成员
			LinkList.this.returnData[LinkList.this.foot++] = this.data;	
			if (this.next != null) {//如果还有下一个节点  继续调用这个方法
				next.toArrayNode();
			}
		}
	}
	//-----------------以下是LinkList的成员属性--------------
	private Node root;			//作为链表的根节点
	private int count;			//作为链表的长度/数量
	private int foot = 0;			//数组下标
	private Object[] returnData;	//返回的数组
	
	//-----------------以下是ILink方法---------------------
	//添加
	@Override
	public void add(E data) {
		if (data == null) {		//保存数据为null
			return;				//结束方法直接返回
		}
		
		Node<E> next = new Node<E>(data);		//创建一个新的节点
		if (this.root == null) {		//没有根节点
			this.root = next;			//第一个节点做为根节点
		}else{	//根节点存在
			this.root.addNode(next);	//当有了根节点,就往下一个节点添加
		}
		
		this.count++;		//每添加一个对象都会加一
	}
	
	//长度
	@Override
	public int size(){
		return this.count;
	}
	
	//判断是否为空
	@Override
	public boolean isEmpty() {
		return this.count == 0;		//true为空,false非空
	}
	
	//数据集合
	@Override
	public Object[] toArray() {
		if (this.isEmpty()) {		//判断谁为空
			return null;			//直接返回
		}
		
		this.foot = 0;				//下标归零
		this.returnData = new Object[this.count];	//因为记录了长度 直接用就行了
		this.root.toArrayNode();	//利用Node进行递归数据获取
		//因为数组是引用类型  所以在上面这个方法获取就行了
		return this.returnData;
	}
	
	//遍历
	@Override
	public void printList() {
		Node<E> next = this.root;		//获取第一个数据
		
		while (true) {					//无限循环
			if (next == null) {			//为null
				break;					//跳出循环
			}
			
			System.out.println(next.data);	//输出数据
			next = next.next;			//获取下一个节点
		}
	}

}

interface ILink<E>{
	
	public void add(E data);		//添加
	public int size();				//长度
	public boolean isEmpty();		//判断链表是否为空
	public Object[] toArray();		//数据集合
	
	public void printList();		//遍历
}

public static void main(String[] args) {
		
		ILink<String> all = new LinkList<String>();
		all.add("Hello");
		all.add("World");
		
		Object[] result = all.toArray();
		for(Object x : result){
			System.out.println(x);
		}
		
	}

输出结果:

Hello
World

根据索引取得数据

链表可以像数组一样进行处理,所以也应该可以像数组一样进行索引数据取得,在这样的情况下就可以继续利用递归的形式来完成。

package amazon;

@SuppressWarnings("all")
public class LinkList<E> implements ILink<E> {
    
	private class Node<E>{
		private E data; 		//存储的数据
		private Node next;		//下一个节点
		
		public Node(E data){	//构造方法,在实例化的时候存储数据
			this.data = data;
		}
		
		public void addNode(Node next){	//保存新的数据
			if (this.next == null) {
				this.next = next;
			}else{
				this.next.addNode(next);
			}
		}
		
		public void toArrayNode(){
			//从内部类获取外部类的私有成员
			
			LinkList.this.returnData[LinkList.this.foot++] = this.data;	
			if (this.next != null) {//如果还有下一个节点  继续调这个方法
				this.next.toArrayNode();
			}
		}
		
		public E getNode(int index){
			if(LinkList.this.foot++ == index){	//索引相同
				return this.data;	//返回当前数据
			}else{
				return (E) this.next.getNode(index);	//递归调用
			}
		}
	}
	//-----------------以下是LinkList的成员属性--------------
	private Node root;			//作为链表的根节点
	private int count;			//作为链表的长度/数量
	private int foot;			//数组下标
	private Object[] returnData;	//返回的数组
	
	//-----------------以下是ILink方法---------------------
	//添加
	@Override
	public void add(E data) {
		if (data == null) {		//保存数据为null
			return;				//结束方法直接返回
		}
		
		Node<E> next = new Node<E>(data);		//创建一个新的节点
		if (this.root == null) {		//没有根节点
			this.root = next;			//第一个节点做为根节点
		}else{	//根节点存在
			this.root.addNode(next);	//当有了根节点,就往下一个节点添加
		}
		
		this.count++;		//每添加一个对象都会加一
	}
	
	//长度
	@Override
	public int size(){
		return this.count;
	}
	
	//判断是否为空
	@Override
	public boolean isEmpty() {
		return this.count == 0;		//true为空,false非空
	}
	
	//数据集合
	@Override
	public Object[] toArray() {
		if (this.isEmpty()) {		//判断谁为空
			return null;			//直接返回
		}
		
		this.foot = 0;				//下标归零
		this.returnData = new Object[this.count];	//因为记录了长度 直接用就行了
		this.root.toArrayNode();	//利用Node进行递归数据获取
		//因为数组是引用类型  所以在上面这个方法获取就行了
		return this.returnData;
	}
	
	//遍历
	@Override
	public void printList() {
		Node<E> next = this.root;		//获取第一个数据
		
		while (true) {					//无限循环
			if (next == null) {			//为null
				break;					//跳出循环
			}
			
			System.out.println(next.data);	//输出数据
			next = next.next;			//获取下一个节点
		}
	}
	
	//根据下标获取数据
	@Override
	public E get(int index){
		if(index >= this.count){	//索引应该在指定范围之内
			return null;
		}
		//索引数据的获取应该有Node类完成 
		this.foot = 0;//重置索引的下标
		return (E) this.root.getNode(index);
	}


}

interface ILink<E>{
	
	public void add(E data);		//添加
	public int size();				//长度
	public boolean isEmpty();		//判断链表是否为空
	public Object[] toArray();		//数据集合
	public E get(int index);		//根据索引取得数据
	
	public void printList();		//遍历
}
public static void main(String[] args) {
		
		ILink<String> all = new LinkList<String>();
		all.add("Hello1");
		all.add("World2");
		all.add("World3");
		
		Object[] result = all.toArray();
		for(Object x : result){
			System.out.println(x);
		}
		System.out.println("-------------------------------");
		System.out.println(all.get(1));
		
	}

输出结果:

Hello1
World2
World3
-------------------------------
World2

修改链表数据

现在可以根据索引来获取指定的数据了,但是既然可以获取数据,也就可以进行数据的修改。

package amazon;

@SuppressWarnings("all")
public class LinkList<E> implements ILink<E> {
    
	private class Node<E>{
		private E data; 		//存储的数据
		private Node next;		//下一个节点
		
		public Node(E data){	//构造方法,在实例化的时候存储数据
			this.data = data;
		}
		
		public void addNode(Node next){	//保存新的数据
			if (this.next == null) {
				this.next = next;
			}else{
				this.next.addNode(next);
			}
		}
		
		public void toArrayNode(){
			//从内部类获取外部类的私有成员 没次加一保证下一次拿到的是加一的foot
			LinkList.this.returnData[LinkList.this.foot++] = this.data;	
			if (this.next != null) {//如果还有下一个节点  继续调这个方法
				this.next.toArrayNode();
			}
		}
		
		public E getNode(int index){
			//从内部类获取外部类的私有成员 没次加一保证下一次拿到的是加一的foot
			if(LinkList.this.foot++ == index){	//索引相同
				return this.data;	//返回当前数据
			}else{
				return (E) this.next.getNode(index);	//递归调用
			}
		}
		
		public void setNode(int index,E data){
			//从内部类获取外部类的私有成员 没次加一保证下一次拿到的是加一的foot
			if(LinkList.this.foot++ == index){	//索引相同
				this.data = data;
			}else{
				this.next.setNode(index, data);
			}
		}
	}
	//-----------------以下是LinkList的成员属性--------------
	private Node root;			//作为链表的根节点
	private int count;			//作为链表的长度/数量
	private int foot;			//数组下标
	private Object[] returnData;	//返回的数组
	
	//-----------------以下是ILink方法---------------------
	//添加
	@Override
	public void add(E data) {
		if (data == null) {		//保存数据为null
			return;				//结束方法直接返回
		}
		
		Node<E> next = new Node<E>(data);		//创建一个新的节点
		if (this.root == null) {		//没有根节点
			this.root = next;			//第一个节点做为根节点
		}else{	//根节点存在
			this.root.addNode(next);	//当有了根节点,就往下一个节点添加
		}
		
		this.count++;		//每添加一个对象都会加一
	}
	
	//长度
	@Override
	public int size(){
		return this.count;
	}
	
	//判断是否为空
	@Override
	public boolean isEmpty() {
		return this.count == 0;		//true为空,false非空
	}
	
	//数据集合
	@Override
	public Object[] toArray() {
		if (this.isEmpty()) {		//判断谁为空
			return null;			//直接返回
		}
		
		this.foot = 0;				//下标归零
		this.returnData = new Object[this.count];	//因为记录了长度 直接用就行了
		this.root.toArrayNode();	//利用Node进行递归数据获取
		//因为数组是引用类型  所以在上面这个方法获取就行了
		return this.returnData;
	}
	
	//遍历
	@Override
	public void printList() {
		Node<E> next = this.root;		//获取第一个数据
		
		while (true) {					//无限循环
			if (next == null) {			//为null
				break;					//跳出循环
			}
			
			System.out.println(next.data);	//输出数据
			next = next.next;			//获取下一个节点
		}
	}
	
	//根据下标获取数据
	@Override
	public E get(int index){
		if(index >= this.count){	//索引应该在指定范围之内
			return null;
		}
		//索引数据的获取应该有Node类完成 
		this.foot = 0;//重置索引的下标
		return (E) this.root.getNode(index);
	}
	
	//根据下标修改数据
	@Override
	public void set(int index, E data) {
		if(index >= this.count){	//索引应该在指定范围之内
			return;
		}
		//索引数据的获取应该有Node类完成 
		this.foot = 0;//重置索引的下标
		this.root.setNode(index, data);
	}
}

interface ILink<E>{
	
	public void add(E data);		//添加
	public int size();				//长度
	public boolean isEmpty();		//判断链表是否为空
	public Object[] toArray();		//数据集合
	public E get(int index);		//根据索引取得数据
	public void set(int index,E data);	//根据索引修改数据
	
	public void printList();		//遍历
}
public static void main(String[] args) {
		
		ILink<String> all = new LinkList<String>();
		all.add("Hello1");
		all.add("World2");
		all.add("World3");
		
		Object[] result = all.toArray();
		for(Object x : result){
			System.out.println(x);
		}
		System.out.println("----------------1---------------");
		System.out.println(all.get(1));
		all.set(1, "萝莉");
		System.out.println("----------------2---------------");
		System.out.println(all.get(1));
	}

输出结果:

Hello1
World2
World3
----------------1---------------
World2
----------------2---------------
萝莉

数据内容查询

在一个集合里面往往需要保存有大量的数据,有些时候需要判断某个数据是否存在,这个时候通过对象比较的模式(eauals())来完成。

package amazon;

@SuppressWarnings("all")
public class LinkList<E> implements ILink<E> {
    
	private class Node<E>{
		private E data; 		//存储的数据
		private Node next;		//下一个节点
		
		public Node(E data){	//构造方法,在实例化的时候存储数据
			this.data = data;
		}
		
		//添加数据
		public void addNode(Node next){	//保存新的数据
			if (this.next == null) {
				this.next = next;
			}else{
				this.next.addNode(next);
			}
		}
		
		//设置成数组
		public void toArrayNode(){
			//从内部类获取外部类的私有成员 没次加一保证下一次拿到的是加一的foot
			LinkList.this.returnData[LinkList.this.foot++] = this.data;	
			if (this.next != null) {//如果还有下一个节点  继续调这个方法
				this.next.toArrayNode();
			}
		}
		
		//根据索引查询数据
		public E getNode(int index){
			//从内部类获取外部类的私有成员 没次加一保证下一次拿到的是加一的foot
			if(LinkList.this.foot++ == index){	//索引相同
				return this.data;	//返回当前数据
			}else{
				return (E) this.next.getNode(index);	//递归调用
			}
		}
		
		//根据索引修改数据
		public void setNode(int index,E data){
			//从内部类获取外部类的私有成员 没次加一保证下一次拿到的是加一的foot
			if(LinkList.this.foot++ == index){	//索引相同
				this.data = data;
			}else{
				this.next.setNode(index, data);//递归调用
			}
		}
		
		//判断数据是否存在
		public boolean containsNode(E data){
			if (this.data.equals(data)) {	//判断数据是否相等
				return true;		//返回true
			}else{	
				if (this.next == null) {	//判断是否还有下一个节点
					return false;	//返回false
				}
			}
			return this.next.containsNode(data);	//递归调用
		}
	}
	//-----------------以下是LinkList的成员属性--------------
	private Node root;			//作为链表的根节点
	private int count;			//作为链表的长度/数量
	private int foot;			//数组下标
	private Object[] returnData;	//返回的数组
	
	//-----------------以下是ILink方法---------------------
	//添加
	@Override
	public void add(E data) {
		if (data == null) {		//保存数据为null
			return;				//结束方法直接返回
		}
		
		Node<E> next = new Node<E>(data);		//创建一个新的节点
		if (this.root == null) {		//没有根节点
			this.root = next;			//第一个节点做为根节点
		}else{	//根节点存在
			this.root.addNode(next);	//当有了根节点,就往下一个节点添加
		}
		
		this.count++;		//每添加一个对象都会加一
	}
	
	//长度
	@Override
	public int size(){
		return this.count;
	}
	
	//判断是否为空
	@Override
	public boolean isEmpty() {
		return this.count == 0;		//true为空,false非空
	}
	
	//数据集合
	@Override
	public Object[] toArray() {
		if (this.isEmpty()) {		//判断谁为空
			return null;			//直接返回
		}
		
		this.foot = 0;				//下标归零
		this.returnData = new Object[this.count];	//因为记录了长度 直接用就行了
		this.root.toArrayNode();	//利用Node进行递归数据获取
		//因为数组是引用类型  所以在上面这个方法获取就行了
		return this.returnData;
	}
	
	//遍历
	@Override
	public void printList() {
		Node<E> next = this.root;		//获取第一个数据
		
		while (true) {					//无限循环
			if (next == null) {			//为null
				break;					//跳出循环
			}
			
			System.out.println(next.data);	//输出数据
			next = next.next;			//获取下一个节点
		}
	}
	
	//根据下标获取数据
	@Override
	public E get(int index){
		if(index >= this.count){	//索引应该在指定范围之内
			return null;
		}
		//索引数据的获取应该有Node类完成 
		this.foot = 0;//重置索引的下标
		return (E) this.root.getNode(index);
	}
	
	//根据下标修改数据
	@Override
	public void set(int index, E data) {
		if(index >= this.count){	//索引应该在指定范围之内
			return;
		}
		//索引数据的获取应该有Node类完成 
		this.foot = 0;//重置索引的下标
		this.root.setNode(index, data);
	}
	
	//判断数据是否存在
	@Override
	public boolean contains(E data) {
		if (data == null) {		//为null返回false
			return false;
		}
		return this.root.containsNode(data);	
	}
}

interface ILink<E>{
	
	public void add(E data);		//添加
	public int size();				//长度
	public boolean isEmpty();		//判断链表是否为空
	public Object[] toArray();		//数据集合
	public E get(int index);		//根据索引取得数据
	public void set(int index,E data);	//根据索引修改数据
	public boolean contains(E data);	//判断数据是否存在
	
	public void printList();		//遍历
}
public static void main(String[] args) {
		
		ILink<String> all = new LinkList<String>();
		all.add("Hello1");
		all.add("World2");
		all.add("World3");
		
		Object[] result = all.toArray();
		for(Object x : result){
			System.out.println(x);
		}
		System.out.println("----------------1---------------");
		System.out.println(all.get(1));
		all.set(1, "萝莉");
		System.out.println("----------------2---------------");
		System.out.println(all.get(1));
		System.out.println("---------------cont------------");
		System.out.println(all.contains("萝莉"));
	}

输出结果:

Hello1
World2
World3
----------------1---------------
World2
----------------2---------------
萝莉
---------------cont------------
true

删除链表数据

数据的删除指的是可以从集合里面删除掉指定的一个数据内容,要实现这个功能依然需要数据比较的支持

package amazon;

@SuppressWarnings("all")
public class LinkList<E> implements ILink<E> {
    
	private class Node<E>{
		private E data; 		//存储的数据
		private Node next;		//下一个节点
		
		public Node(E data){	//构造方法,在实例化的时候存储数据
			this.data = data;
		}
		
		//添加数据
		public void addNode(Node next){	//保存新的数据
			if (this.next == null) {
				this.next = next;
			}else{
				this.next.addNode(next);
			}
		}
		
		//设置成数组
		public void toArrayNode(){
			//从内部类获取外部类的私有成员 没次加一保证下一次拿到的是加一的foot
			LinkList.this.returnData[LinkList.this.foot++] = this.data;	
			if (this.next != null) {//如果还有下一个节点  继续调这个方法
				this.next.toArrayNode();
			}
		}
		
		//根据索引查询数据
		public E getNode(int index){
			//从内部类获取外部类的私有成员 没次加一保证下一次拿到的是加一的foot
			if(LinkList.this.foot++ == index){	//索引相同
				return this.data;	//返回当前数据
			}else{
				return (E) this.next.getNode(index);	//递归调用
			}
		}
		
		//根据索引修改数据
		public void setNode(int index,E data){
			//从内部类获取外部类的私有成员 没次加一保证下一次拿到的是加一的foot
			if(LinkList.this.foot++ == index){	//索引相同
				this.data = data;
			}else{
				this.next.setNode(index, data);//递归调用
			}
		}
		
		//判断数据是否存在
		public boolean containsNode(E data){
			if (this.data.equals(data)) {	//判断数据是否相等
				return true;		//返回true
			}else{	
				if (this.next == null) {	//判断是否还有下一个节点
					return false;	//返回false
				}
			}
			return this.next.containsNode(data);	//递归调用
		}
		
		//删除节点
		public void removeNode(Node previous,E data){
			if (this.data.equals(data)) {
				previous.next = this.next;	//上一个节点的下一个节点变成要删除节点的下一个
			}else{
				if (this.next != null) {	//有后续节点
					this.next.removeNode(this, data);	//向后继续寻找data数据相等的节点
				}
			}
		}
	}
	//-----------------以下是LinkList的成员属性--------------
	private Node root;			//作为链表的根节点
	private int count;			//作为链表的长度/数量
	private int foot;			//数组下标
	private Object[] returnData;	//返回的数组
	
	//-----------------以下是ILink方法---------------------
	//添加
	@Override
	public void add(E data) {
		if (data == null) {		//保存数据为null
			return;				//结束方法直接返回
		}
		
		Node<E> next = new Node<E>(data);		//创建一个新的节点
		if (this.root == null) {		//没有根节点
			this.root = next;			//第一个节点做为根节点
		}else{	//根节点存在
			this.root.addNode(next);	//当有了根节点,就往下一个节点添加
		}
		
		this.count++;		//每添加一个对象都会加一
	}
	
	//长度
	@Override
	public int size(){
		return this.count;
	}
	
	//判断是否为空
	@Override
	public boolean isEmpty() {
		return this.count == 0;		//true为空,false非空
	}
	
	//数据集合
	@Override
	public Object[] toArray() {
		if (this.isEmpty()) {		//判断谁为空
			return null;			//直接返回
		}
		
		this.foot = 0;				//下标归零
		this.returnData = new Object[this.count];	//因为记录了长度 直接用就行了
		this.root.toArrayNode();	//利用Node进行递归数据获取
		//因为数组是引用类型  所以在上面这个方法获取就行了
		return this.returnData;
	}
	
	//遍历
	@Override
	public void printList() {
		Node<E> next = this.root;		//获取第一个数据
		
		while (true) {					//无限循环
			if (next == null) {			//为null
				break;					//跳出循环
			}
			
			System.out.println(next.data);	//输出数据
			next = next.next;			//获取下一个节点
		}
	}
	
	//根据下标获取数据
	@Override
	public E get(int index){
		if(index >= this.count){	//索引应该在指定范围之内
			return null;
		}
		//索引数据的获取应该有Node类完成 
		this.foot = 0;//重置索引的下标
		return (E) this.root.getNode(index);
	}
	
	//根据下标修改数据
	@Override
	public void set(int index, E data) {
		if(index >= this.count){	//索引应该在指定范围之内
			return;
		}
		//索引数据的获取应该有Node类完成 
		this.foot = 0;//重置索引的下标
		this.root.setNode(index, data);
	}
	
	//判断数据是否存在
	@Override
	public boolean contains(E data) {
		if (data == null) {		//为null返回false
			return false;
		}
		return this.root.containsNode(data);	
	}
	
	//删除数据
	@Override
	public void remove(E data) {
		if (this.contains(data)) {		//判断是否存在
			if (this.root.data.equals(data)) {		//根节点处理
				this.root = this.root.next;			//根引用根的下一个节点
			}else{					//如果不是根节点
				this.root.removeNode(this.root, data);
			}
		}
	}
	
	//清空
	@Override
	public void clean() {
		this.root =null;	//后续的节点都没了
		this.count = 0;		//数组长度清零
	}
}

interface ILink<E>{
	
	public void add(E data);		//添加
	public int size();				//长度
	public boolean isEmpty();		//判断链表是否为空
	public Object[] toArray();		//数据集合
	public E get(int index);		//根据索引取得数据
	public void set(int index,E data);	//根据索引修改数据
	public boolean contains(E data);	//判断数据是否存在
	public void remove(E data);		//删除数据
	public void clean();			//清空
	
	public void printList();		//遍历
}
public static void main(String[] args) {
		
		ILink<String> all = new LinkList<String>();
		all.add("萝莉1");
		all.add("萝莉2");
		all.add("萝莉3");
		
		all.printList();
		System.out.println("------------------***------------------");
		all.remove("萝莉1");
		
		all.printList();
	}

输出结果:

萝莉1
萝莉2
萝莉3
------------------***------------------
萝莉2
萝莉3

综合实战:宠物商店

有空写

综合实战:超市购物车

有空写

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值