java链表增删查改等功能的实现

链表的基本开发结构

class Link { 				// 链表类,外部能够看见的只有这一个类
	private class Node { 			// 定义的内部节点类
		private String data; 		// 要保存的数据
		private Node next; 		// 下一个节点引用
		public Node(String data) {	// 每一个Node类对象都必须保存有相应的数据
			this.data = data;
		}
	}
	// ===================== 以上为内部类 ===================
	private Node root; 			// 根节点定义
}

在本结构中将Node定义为了Link的私有内部类,这样做有两个好处:

  · Node类只会为Link类服务,并且可以利用Node类匹配节点关系;

  · 外部类与内部类之间方便进行私有属性的直接访问,所以不需要在Node类中定义settergetter方法。


数据增加:public void add(数据类型 变量)

public void add(Stringdata) {  //假设不允许有空

if (data == null) { //判断数据是否为空

 return }

Node newNode = new Node(data); //要保存的数据

if (this.root == null) {  //当前没有根节点

  this.root = newNode; //保存根节点

} else {  

this.root.addNode(newNode); //让node类来处理保存数据

}  }


取得保存元素个数: public int size()

  privateint count = 0 ; //保存元素的个数

publicint size() {  //取得保存的数据量

  returnthis.count;

  }


判断是否是空链表: public boolean isEmpty ()

所谓的空链表(不是 null )指的是链表之中不保存任何的数据,空链表判断实际上可以通过两种方式完成:
   Ø 第一种:判断 root 有对象(是否为 null );
   Ø 第二种:判断保存的数据量( count )。
/**
	 * 判断是否是空链表,表示长度为0,不是null
	 * @return 如果链表中没有保存任何的数据则返回true,否则返回false
	 */
	public boolean isEmpty() {
		return this.count == 0;
	}
数据查询: public boolean contains( 数据类型 变量 )
   Ø 在链表之中一定会保存有多个数据,那么基本的判断数据是否存在的方式。以: String 为例( equals() 方法判断),在判断一个字符串是否存在时需要循环链表中的全部内容,并且与要查询的数据进行匹配,如果查找到了则返回 true ,否则返回 false


Node 类增加方法

/**
		 * 数据检索操作,判断指定数据是否存在
		 * 第一次调用(Link):this = Link.root
		 * 第二次调用(Node):this = Link.root.next
		 * @param data 要查询的数据
		 * @return 如果数据存在返回true,否则返回false
		 */
		public boolean containsNode(String data) {
			if (data.equals(this.data)) { 	// 当前节点数据为要查询的数据
				return true; 		// 后面不再查询了
			} else { 		// 当前节点数据不满足查询要求
				if (this.next != null) { 	// 有后续节点
					return this.next.containsNode(data);// 递归调用继续查询
				} else { 		// 没有后续节点
					return false; 	// 没有查询到返回false
				}
			}
		}
修改 Link

/**
	 * 数据查询操作,判断指定数据是否存在,如果链表没有数据直接返回false
	 * @param data 要判断的数据
	 * @return 数据存在返回true,否则返回false
	 */
	public boolean contains(String data) {
		if (data == null || this.root == null) {	// 现在没有要查询的数据,根节点也不保存数据
			return false ;		// 没有查询结果
		}
		return this.root.containsNode(data) ;	// 交由Node类查询
	}
根据索引取得数据: public 数据类型 get( int index)

    Ø 链表本身就属于一种动态的对象数组,与普通的对象数组相比最大的优势就在于没有长度限制。那么既然链表属于动态对象数组,也就应该具备像数组那样可以根据索引取得元素的功能,自然也就能根据指定索引取得指定节点数据的操作

Link 类添加处理程序

Link类里面增加一个foot的属性,表示每一个Node元素的编号

privateintfoot = 0 ;  // 节点索引

在每一次查询的时候(一个链表可能查询多次),那么foot应该在每一次查询时都从头开始计算(foot设为0);

/**
	 * 根据索引取得保存的节点数据
	 * @param index 索引数据
	 * @return 如果要取得的索引内容不存在或者大于保存个数返回null,反之返回数据
	 */
	public String get(int index) {
		if (index > this.count) {	// 超过了查询范围
			return null ;	// 没有数据
		}
		this.foot = 0 ;		// 表示从前向后查询
		return this.root.getNode(index) ;	// 查询过程交给Node类
	}
Node 类里面实现 getNode () 方法

/**
		 * 根据索引取出数据,此时该索引一定是存在的
		 * @param index 要取得数据的索引编号
		 * @return 返回指定索引节点包含的数据
		 */
		public String getNode(int index) {
		// 使用当前的foot内容与要查询的索引进行比较,随后将foot的内容自增,目的是为了下次查询方便
			if (Link.this.foot++ == index) {	// 当前为要查询的索引
				return this.data; // 返回当前节点数据
			} else { 			// 继续向后查询
				return this.next.getNode(index);	// 进行下一个节点的判断
			}
		}
修改指定索引内容: public void set( int index, 数据类型 变量 )

/**
		 * 修改指定索引节点包含的数据
		 * @param index 要修改的索引编号
		 * @param data 新数据
		 */
		public void setNode(int index, String data) {
			// 使用当前的foot内容与要查询的索引进行比较,随后将foot的内容自增,目的是为了下次查询方便
			if (Link.this.foot++ == index) {	// 当前为要修改的索引
				this.data = data; 	// 进行内容的修改
			} else {
			this.next.setNode(index, data);// 继续下一个节点的索引判断
			}
		}
Link 类里面增加 set() 方法

/**
	 * 根据索引修改数据
	 * @param index 要修改数据的索引编号
	 * @param data 新的数据内容
	 */
	public void set(int index, String data) {
		if (index > this.count) {		// 判断是否超过了保存范围
			return; 		// 结束方法调用
		}
		this.foot = 0; 	// 重新设置foot属性的内容,作为索引出现
		this.root.setNode(index, data); 	// 交给Node类设置数据内容
	}
数据删除: public void remove( 数据类型 变量 )

   Ø 对于链表之中的内容,之前完成的是增加操作和查询操作,但是从链表之中也会存在删除数据的操作,可是删除数据的操作需要分两种情况讨论。

情况一:

   Ø 要删除的数据是根节点,则 root 应该变为“根节点 .next ”(根节点的下一个节点为新的根节点),并且由于根节点需要被 Link 类所,所以此种情况要在 Link 类中进行处理

情况二:

  Ø 要删除的不是根节点,而是其它的普通节点,这个时候删除节点的操作应该放在 Node 类里处理,并且由于 Link 类已经判断过根节点,所以此处应该从第二个节点开始判断的

Node 类里面增加一个 removeNode () 方法

/**
	 * 节点的删除操作,匹配每一个节点的数据,如果当前节点数据符合删除数据,
	 * 则使用“当前节点上一节点.next = 当前节点.next”方式空出当前节点
	 * 第一次调用(Link),previous = Link.root、this = Link.root.next
	 * 第二次调用(Node),previous = Link.root.next、this = Link.root.next.next
	 * @param previous 当前节点的上一个节点
	 * @param data 要删除的数据
	 */
	public void removeNode(Node previous, String data) {
		if (data.equals(this.data)) { 	// 当前节点为要删除节点
			previous.next = this.next; 	// 空出当前节点
		} else { 			// 应该向后继续查询
			this.next.removeNode(this, data);	// 继续下一个判断
			}
		}
Link 类里面增加根节点的判断

/**
	 * 链表数据的删除操作,在删除前要先使用contains()判断链表中是否存在有指定数据
	 * 如果要删除的数据存在则首先判断根节点的数据是否为要删除数据
	 * 如果是则将根节点的下一个节点作为新的根节点
	 * 如果要删除的数据不是根节点数据,则将删除操作交由Node类的removeNode()方法完成
	 * @param data 要删除的数据
	 */
	public void remove(String data) {
		if (this.contains(data)) { 	// 主要功能是判断数据是否存在
			// 要删除数据是否是根节点数据,root是Node类的对象,此处直接访问了内部类的私有操作
			if (data.equals(this.root.data)) { 	// 根节点数据为要删除数据
				this.root = this.root.next; 	// 空出当前根节点
			} else { 		// 根节点数据不是要删除数据
				// 此时根元素已经判断过了,从第二个元素开始判断,即第二个元素的上一个元素为根节点
				this.root.next.removeNode(this.root, data);
			}
			this.count--; 	// 删除成功后个数要减少
		}
	}
将链表变为对象数组: public 数据类型 [] toArray ()

    Ø 对于链表的这种数据结构,在实际的开发之中,最为关键的是两个操作:增加数据、取得全部数据,而链表本身属于一种动态的对象数组,所以在链表输出时,最好的做法是将链表中所保存的数据以对象数组的方式返回,而这个返回的对象数组长度也应该是根据保存数据的个数来决定的

修改Link类的定义

   增加一个返回的数组属性内容,之所以将其定义为属性,是因为内部类和外部类都可以访问

private String []retArray//返回的数组


增加 toArray () 方法:
/**
	 * 将链表中的数据转换为对象数组输出
	 * @return 如果链表没有数据返回null,如果有数据则将数据变为对象数组后返回
	 */
	public String[] toArray() {
		if (this.root == null) {	// 判断链表是否有数据
			return null;	// 没有数据返回null
		}
		this.foot = 0; // 脚标清零操作
		this.retArray = new String[this.count];	// 根据保存内容开辟数组
		this.root.toArrayNode(); // 交给Node类处理
		return this.retArray;	// 返回数组对象
	}
Node 类里面处理数组数据的保存
/**
		 * 将节点中保存的内容转化为对象数组
		 * 第一次调用(Link):this = Link.root;
		 * 第二次调用(Node):this = Link.root.next;
		 */
		public void toArrayNode() {
			Link.this.retArray[Link.this.foot++] = this.data;	// 取出数据并保存在数组之中
			if (this.next != null) { 	// 有后续元素
				this.next.toArrayNode();	// 继续下一个数据的取得
			}
		}
清空链表: public void clear()

public void clear() {
		this.root = null;		// 清空链表
		this.count = 0;		// 元素个数为0
	}

















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值