Java模拟单向链表

使用Java模拟链表

单向链表

单向链表的特点

	单向链表也是有序的链表,但是这个有序指的是元素在逻辑上的顺序,而不是在物理内存中分布的顺序,物理内存中的顺序不一定是连续的.

值得一提的是链表以节点的方式来存储数据,每一个节点中既维护着存储的数据信息,有维护着下一个节点的地址信息.
单向链表还可以分为有头结点的单向链表和没有头节点的单向链表.
单向链表的各个节点不一定是连续分布的,只是在逻辑上是连续的.

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实现思路

1 这个链表中需要有一个head属性来指向链表的第一个元素,这个head也是一个Node节点,只不过不让其存储任何数据,只是用来记录下一个节点的地址信息.

2 每一个Node节点都需要维护各自的数据和下一个节点的地址信息.

3 如果某一个节点的next属性为空,则该节点就是链表中的最后一个节点.

实现代码

package element.io.data.structure.d3;

import lombok.Data;

import java.io.Serializable;
import java.util.Comparator;

/**
 * @author 张晓华
 * @date 2022-12-17
 * 模拟带有头节点的单向链表
 * head 头结点,不存储数据,只保存实际的头节点元素的地址信息
 */
public class SingleLinkedList<T> {

	// 头节点,并不会用来实际存储数据,只是保存链表头结点的地址信息
	private Node head;

	public SingleLinkedList() {
		this.head = new Node(null);
	}

	public void add(final T data) {
		Node temp = head;
		while (true) {
			// 找到最后一个节点
			if (temp.next == null) {
				break;
			}
			// 控制指针向后移动,指针需要不断地移动才能够实现遍历
			temp = temp.next;
		}
		// 让最后一个节点的next指向新添加的节点
		temp.next = new Node(data);
	}

	public void addInOrder(final T data, Comparator<T> comparator) {
		Node temp = head;
		boolean flag = false;
		// 找到可以满足条件的节点的前一个节点位置,因为要执行的插入操作,所以需要在两个节点之间操作
		while (true) {
			if (temp.next == null) {
				flag = true;
				break;
			} else if (comparator.compare(temp.next.data, data) > 0) {
				flag = true;
				break;
			} else if (comparator.compare(temp.next.data, data) == 0) {
				break;
			} else {
				temp = temp.next;
			}
		}
		if (flag) {
			// 找到了要插入的节点的位置后,
			// 创建一个新的节点,让前一个节点的next指向新节点,新节点的next指向前一个节点的next
			Node newNode = new Node(data);
			newNode.next = temp.next;
			temp.next = newNode;
		}
	}

	public void list() {
		Node temp = head;
		if (temp.next == null) {
			return;
		}
		while (temp.next != null) {
			// 这里之所以要next.data是因为head节点并没有存储数据
			System.out.println(temp.next.data);
			// 指针后移
			temp = temp.next;
		}
	}

	public T getHead() {
		if (head.next == null) {
			return null;
		}
		return head.next.data;
	}


	public void update(final T data, Comparator<T> comparator) {
		Node temp = head;
		if (temp.next == null) {
			return;
		}
		while (true) {
			// 直接找到匹配的节点的前一个节点,然后创建一个新的节点,让新的节点的next指向原来数据的next指向的节点,
			// 直接替换掉原来的节点,这个条件必须前置,否则就会出现空指针异常
			if (temp.next == null) {
				break;
			} else if (comparator.compare(temp.next.data, data) == 0) {
				Node newNode = new Node(data);
				//temp.next.next 它为空并没有什么实质性的影响
				newNode.next = temp.next.next;
				temp.next = newNode;
				break;
			} else {
				temp = temp.next;
			}
		}
	}


	public void remove(final T data, Comparator<T> comparator) {
		Node temp = head;
		if (head.next == null) {
			return;
		}
		while (true) {
			// 同样是需要找到删除的节点的前一个节点,直接将其前一个节点的next指向要删除指点的next指向的节点,
			// 当前要删除的数据没有被任何变量所引用时JVM会就自动地回收内存空间
			if (comparator.compare(temp.next.data, data) == 0) {
				temp.next = temp.next.next;
				break;
			} else if (temp.next == null) {
				break;
			} else {
				temp = temp.next;
			}
		}
	}

	public boolean isLast(Node node) {
		return head.next == null;
	}

	@Data
	public class Node implements Serializable {

		private Node next;
		private T data;

		public Node(T data) {
			this.data = data;
		}
	}


}

测试demo

public static void demo() {
		SingleLinkedList<Hero> linkedList = new SingleLinkedList<>();
		Hero song = Hero.builder().seq(1).name("宋江").nickName("及时雨").build();
		linkedList.add(song);
		Hero lin = Hero.builder().seq(2).name("林冲").nickName("豹子头").build();
		linkedList.add(lin);
		Hero wu = Hero.builder().seq(3).name("吴用").nickName("智多星").build();
		linkedList.add(wu);
		linkedList.list();
		Hero wu2 = Hero.builder().seq(3).name("吴用").nickName("智多星").build();
		wu2.setNickName("军师");
		wu2.setSeq(10);
		linkedList.update(wu2, Comparator.comparing(Hero::getSeq));
		System.out.println("修改后的链表");
		linkedList.list();
		System.out.println("删除数据后的链表");
		linkedList.remove(wu,Comparator.comparing(Hero::getSeq));
		linkedList.list();
	}

public static void demo2() {
		SingleLinkedList<Hero> linkedList = new SingleLinkedList<>();
		Hero song = Hero.builder().seq(1).name("宋江").nickName("及时雨").build();
		linkedList.addInOrder(song,Comparator.comparing(Hero::getSeq));
		Hero wu = Hero.builder().seq(3).name("吴用").nickName("智多星").build();
		linkedList.addInOrder(wu,Comparator.comparing(Hero::getSeq));
		Hero lin = Hero.builder().seq(3).name("林冲").nickName("豹子头").build();
		linkedList.addInOrder(lin,Comparator.comparing(Hero::getSeq));
		linkedList.list();
	}

运行结果:
image-20221217122312723
在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值