单向链表的Java实现

单向链表的Java实现

首先在了解单向链表之前,简单说一下普通数组存在的致命缺陷,即普通数组一旦定义,那么它的长度便不可更改,而链表可以解决这样的缺陷,比如在超市购物时,买了一瓶饮料,两瓶洗衣液,突然我看见货架的另外一边还有另外一种品牌的洗衣液,此刻若是想要换掉一瓶洗衣液,那么我需要从之前已经挑好的两瓶中放回货架,类似于数组的删除操作,显然在已知想要买多少东西的时候是可以使用简单数组的,可要是临时有需要加一点呢?此时就轮到了链表动态数组)。

部分实现代码:

package stu.java.lch;
//1、数据增加               2、获取数据个数         3、空集合判断      
//4、返回链表数据   		 5、获取指定索引数据      
//6、修改指定索引的数据      7、判断指定数据是否存在
//8、数据删除               9、清空集合(链表)
  
interface ILink<E> {            //设置泛型,链表的标准
	public void add(E e) ;      //1、数据增加
	public int size() ;         //2、获取数据个数
	public boolean isEmpty() ;  //3、判断是否为空
	public Object [] toArray() ;//4、将链表(集合)元素以数组的形式返回
	public E get(int index) ;   //5、根据索引获取数据
	public void set(int index, E data) ; //6、修改索引数据
	public boolean contains(E data) ;    //7、判断指定数据是否存在
	public void remove(E e) ;            //8、数据删除
	public void clean() ;                //9、清空集合(链表)
}
class LinkImpl<E> implements ILink<E> {
	private class Node {        //保存节点的数据关系
		private E data ;        //保存的数据
		private Node next ;       //保存下一个引用
		public Node(E data) {    //有数据的情况下才有意义
			this.data = data ;
		}
		public void addNode(Node newNode) {   //保存新的Node数据
			if (this.next == null) {     //当前节点的下一个节点为null
				this.next = newNode ;    //保存当前节点
			} else {
				this.next.addNode(newNode);
			}
		}
		public void toArrayNode() {
			//4、将当前节点的数据取出保存到returnData数组中,同时进行索引自增
			LinkImpl.this.returnData [LinkImpl.this.foot ++ ] = this.data ;
			if (this.next != null) {    //4、还有下一个数据
				this.next.toArrayNode();
			}
		}
		//5、
		public E getNode(int index) {
			if (LinkImpl.this.foot ++ == index) {         //索引相同
				return this.data ;       //返回当前数据
			} else {
				return this.next.getNode(index) ;
			}
		}
		//6、
		public void setNode(int index, E data) {
			if (LinkImpl.this.foot ++ == index) {         //索引相同
				this.data = data ;                        //6、修改数据
			} else {
				this.next.setNode(index,data) ;
			}
		}
		//7、
		public boolean containsNode(E data) {
			if (data.equals(this.data)) {            //7、对象比较
				return true ;
			} else {
				if (this.next == null) {              //7、没有后续节点了
					return false ;             //找不到
				} else {
					return this.next.containsNode(data) ;  //向后继续判断
				}
			}
		}
		//8、
		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);   //向后继续删除
				}
			}
		}
	}
	//-----------------以下为Link类中定义的成员--------------------
	private Node root ;    //保存根元素
	private int count ;     //2、保存数据的个数
	private int foot ;        //4、描述的是操作数组的脚标
	private Object [] returnData ;//4、返回的数据保存
	//-----------------以下为Link类中定义的方法--------------------
	public void add(E e) {
		if (e == null) {            //保存的数据为空
			return ;
		}
		//数据本身是不具有关联特性的,只有Node类有,要想实现关联关系必须将数据包装在Node类中
		Node newNode = new Node(e) ;  //创建一个新的节点
		if (this.root == null) {
			this.root = newNode ;//第一个节点作为根节点
		} else {
			this.root.addNode(newNode) ;  //将新节点保存在合适的位置
		}
		this.count ++ ;      //2、保存元素个数自增
	}
	public int size() {
		return this.count ;   //2、返回元素个数
	}
	public boolean isEmpty() {
		return this.count == 0 ;
	}
	//4、
	public Object[] toArray() {
		if (this.isEmpty()) {
			return null ;
			//throw new NullPointerException("集合内容为空") ;
		}
		this.foot = 0 ;       //4、脚标清零
		this.returnData = new Object [this.count] ;  //4、根据已有的长度开辟数组
		this.root.toArrayNode();      //4、利用Node类进行递归数据获取
		return this.returnData ;       //4、返回全部元素
	}
	//5、
	public E get(int index) {
		if (index >= this.count) {  //5、索引应该在指定范围之内
			return null ;
		}  //索引数据的获取应该由Node类完成
		this.foot = 0 ;       //重置索引的下标
		return this.root.getNode(index) ;
	}
	//6、
	public void set(int index,E data) {
		if (index >= this.count) {  //6、索引应该在指定范围之内
			return ;                //方法结束
		}  //索引数据的获取应该由Node类完成
		this.foot = 0 ;       //重置索引的下标
		this.root.setNode(index,data) ;  //修改数据
	}
	//7、
	public boolean contains(E data) {
		if (data == null) {
			return false ;               //没有数据
		} 
		return this.root.containsNode(data) ;  //交给Node类判断
	}
	//8、
	public void remove(E data) {
		if (this.contains(data)) {    //判断数据是否存在
			if (this.root.data.equals(data)) {    //根节点为要删除节点
				this.root = this.root.next ;      //根的下一个节点
			} else {      //交给Node类进行删除
				this.root.next.removeNode(this.root, data);
			}
			this.count -- ;
		}
	}
	//9、
	public void clean() {
		this.root = null ;   //后续所有节点都没了
		this.count = 0 ;     //个数清零
	}
}

若有不当之处,请各位大佬给予指正。
注:若有侵权,请联系作者删除,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值