java手动实现单向链表

  单向链表是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从第一个开始。这里我们用java来实现一下单向链表。
	和普通的线性结构(如数组)相比,链表结构有以下特点:
(1)单个结点创建非常灵活,普通的线性内存通常在创建的时候就需要设定数据的大小
(2)结点的删除、插入非常方便,不需要像线性结构那样移动剩下的数据
(3)结点的访问方便,可以通过循环或者递归的方法访问到任意数据,但是平均的访问效率低于线性表
public class SingleLinkedList {
	//这里不需要数组,不需要其他的复杂的结构,我只要记录单向链表的“头”结点
	private Node first;//first中记录的是第一个结点的地址
	private int total;//这里我记录total是为了后面处理的方便,例如:当用户获取链表有效元素的个数时,不用现数,而是直接返回total等
	
	/*
	 * 内部类,因为这种Node结点的类型,在别的地方没有用,只在单向链表中,用于存储和表示它的结点关系。
	 * 因为我这里涉及为内部类型。
	 */
	private class Node{
		Object data;//因为数据可以是任意类型的对象,所以设计为Object
		Node next;//因为next中记录的下一个结点的地址,因此类型是结点类型
		//这里data,next没有私有化,是希望在外部类中可以不需要get/set,而是直接“结点对象.data","结点对象.next"使用
		Node(Object data, Node next){
			this.data = data;
			this.next = next;
		}
	}
	
	public void add(Object obj){
		/*
		 * (1)把obj的数据,包装成一个Node类型结点对象
		 * (2)把新结点“链接”当前链表的最后
		 * ①当前新结点是第一个结点
		 * 如何判断是否是第一个   if(first==null)说明暂时还没有第一个
		 * ②先找到目前的最后一个,把新结点链接到它的next中
		 * 如何判断是否是最后一个   if(某个结点.next == null)说明这个结点是最后一个
		 */
//		(1)把obj的数据,包装成一个Node类型结点对象
		//这里新结点的next赋值为null,表示新结点是最后一个结点
		Node newNode = new Node(obj, null);
		
		//①当前新结点是第一个结点
		if(first == null){
			//说明newNode是第一个
			first = newNode;
		}else{
			//②先找到目前的最后一个,把新结点链接到它的next中
			Node node = first;
			while(node.next != null){
				node = node.next;
			}
			//退出循环时node指向最后一个结点
			
			//把新结点链接到它的next中
			node.next = newNode;
		}
		
		total++;
	}
	
	public int size(){
		return total;
	}
	
	public Object[] getAll(){
		//(1)创建一个数组,长度为total
		Object[] all = new Object[total];
		
		//(2)把单向链表的每一个结点中的data,拿过来放到all数组中
		Node node = first;
		for (int i = 0; i < total; i++) {
//			all[i] = 结点.data;
			all[i] = node.data;
			//然后node指向下一个
			node = node.next;
		}
		
		//(3)返回数组
		return all;
	}
	
	public void remove(Object obj){
		if(obj == null){
			//(1)先考虑是否是第一个
			if(first!=null){//链表非空
				
				//要删除的结点正好是第一个结点
				if(first.data == null){
					//让第一个结点指向它的下一个
					first = first.next;
					total--;
					return;
				}
				
				//要删除的不是第一个结点
				Node node = first.next;//第二个结点
				Node last = first;
				while(node.next!=null){//这里不包括最后一个,因为node.next==null,不进入循环,而node.next==null是最后一个
					if(node.data == null){
						last.next = node.next;
						total--;
						return;
					}
					last = node;
					node = node.next;
				}
				
				//单独判断最后一个是否是要删除的结点
				if(node.data == null){
					//要删除的是最后一个结点
					last.next = null;
					total--;
					return;
				}
			}
		}else{
			//(1)先考虑是否是第一个
			if(first!=null){//链表非空
				
				//要删除的结点正好是第一个结点
				if(obj.equals(first.data)){
					//让第一个结点指向它的下一个
					first = first.next;
					total--;
					return;
				}
				
				//要删除的不是第一个结点
				Node node = first.next;//第二个结点
				Node last = first;
				while(node.next!=null){//这里不包括最后一个,因为node.next==null,不进入循环,而node.next==null是最后一个
					if(obj.equals(node.data)){
						last.next = node.next;
						total--;
						return;
					}
					last = node;
					node = node.next;
				}
				
				//单独判断最后一个是否是要删除的结点
				if(obj.equals(node.data)){
					//要删除的是最后一个结点
					last.next = null;
					total--;
					return;
				}
			}
		}
	}

	public int indexOf(Object obj){
		if(obj == null){
			Node node = first;
			for (int i = 0; i < total; i++) {
				if(node.data == null){
					return i;
				}
				node = node.next;
			}
		}else{
			Node node = first;
			for (int i = 0; i < total; i++) {
				if(obj.equals(node.data)){
					return i;
				}
				node = node.next;
			}
		}
		return -1;
	}
}

单链表的物理结构:
在这里插入图片描述
双链表的物理结构:
在这里插入图片描述
单向链表的指向关系:
在这里插入图片描述
单向链表的添加过程演示:
在这里插入图片描述
单向链表是空链表状态:
在这里插入图片描述

单向链表查询最后一个节点:
在这里插入图片描述
单向链表删除某个节点:
在这里插入图片描述

再写个测试类用于测试:

public class TestSingleLinkedList {

	public static void main(String[] args) {
		SingleLinkedList list = new SingleLinkedList();
		
		list.add("张三");
		list.add("李四");
		list.add("王五");
		list.add("赵六");
		list.add("钱七");
		
		System.out.println("元素个数:" + list.size());
	
		Object[] all = list.getAll();
		System.out.println(Arrays.toString(all));
		
		/*list.remove("张三");
		System.out.println("元素个数:" + list.size());
		all = list.getAll();
		System.out.println(Arrays.toString(all));
		
		list.remove("王五");
		System.out.println("元素个数:" + list.size());
		all = list.getAll();
		System.out.println(Arrays.toString(all));
		
		list.remove("钱七");
		System.out.println("元素个数:" + list.size());
		all = list.getAll();
		System.out.println(Arrays.toString(all));*/
		
		System.out.println(list.indexOf("张三"));
		System.out.println(list.indexOf("王五"));
		System.out.println(list.indexOf("钱七"));
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值