数据结构基础之单链表(java实现)

136 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

1.链表是以节点的方式来存储,是链式存储 , 每个节点包含 data 域, next 域:指向下一个节点.

单链表的应用举例:

(1)先构造一个单链表对象

class HeroNode{
	int no;
	String name;
	String nickName;
	HeroNode next;//指向下一个节点
	
	public HeroNode(int no,String name,String nickName) {
	this.no = no;
	this.name = name;
	this.nickName = nickName;
	}
}

2.添加数据进单链表

首先初始化一个头结点,因为头结点不能动,然后通过一个辅助变量temp来进行遍历链表,找到链表的最后节点,然后把最后节点的下一个节点(就是null)改为指向新加的节点

//先初始化一个头节点, 头节点不要动, 不存放具体的数据
	private HeroNode head = new HeroNode(0, "", "");
//添加节点到单向链表
	//思路,当不考虑编号顺序时
	//1. 找到当前链表的最后节点
	//2. 将最后这个节点的next 指向 新的节点
	public void add(HeroNode heroNode) {
		
		//因为head节点不能动,因此我们需要一个辅助遍历 temp
		HeroNode temp = head;
		//遍历链表,找到最后
		while(true) {
			//找到链表的最后
			if(temp.next == null) {//
				break;
			}
			//如果没有找到最后, 将将temp后移
			temp = temp.next;
		}
		//当退出while循环时,temp就指向了链表的最后
		//将最后这个节点的next 指向 新的节点
		temp.next = heroNode;
	}

3.按顺序添加数据进单链表

首先也是初始化一个头结点来进行辅助遍历,和设置一个boolean值来查看添加的编号是否已存在,设置好之后,先通过temp遍历发现三种情况,第一种:如果temp的下一个节点为空,则temp在链表的最后,直接添加进temp的下一个节点即可;第二种:如果temp的下一个节点的编号大于所要添加的数据节点,则把temp的下一个节点修改为新加的数据节点,而新的数据节点的下一个节点则修改为原先的temp的下一个节点(heroNode.next = temp.next;  temp.next = heroNode;);第三种:如果所添加进去节点的编号已经存在,则boolean为true,说明编号存在,不能进行添加.

	//第二种方式在添加英雄时,根据排名将英雄插入到指定位置
	//(如果有这个排名,则添加失败,并给出提示)
	public void addByOrder(HeroNode heroNode) {
		//因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助找到添加的位置
		//因为单链表,因为我们找的temp 是位于 添加位置的前一个节点,否则插入不了
		HeroNode temp = head;
		boolean flag = false; // flag标志添加的编号是否存在,默认为false
		while(true) {
			if(temp.next == null) {//说明temp已经在链表的最后
				break; //
			} 
			if(temp.next.no > heroNode.no) { //位置找到,就在temp的后面插入
				break;
			} else if (temp.next.no == heroNode.no) {//说明希望添加的heroNode的编号已然存在
				
				flag = true; //说明编号存在
				break;
			}
			temp = temp.next; //后移,遍历当前链表
		}
		//判断flag 的值
		if(flag) { //不能添加,说明编号存在
			System.out.printf("准备插入的英雄的编号 %d 已经存在了, 不能加入\n", heroNode.no);
		} else {
			//插入到链表中, temp的后面
			heroNode.next = temp.next;
			temp.next = heroNode;
		}
	}

4.删除单链表的数据

根据删除数据的编号来查找这条数据,最主要的一句是temp.next =temp.next.next;把temp的下一个节点数据(也就是要被删除数据的编号)指向为被删除数据的编号,而这样可以使得java的垃圾回收机制去回收没有被引用的数据(要被删除的数据)来进行一个删除

	public void delete(HeroNode delheroNode) {
		//因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助找到添加的位置
		//因为单链表,因为我们找的temp 是位于 添加位置的前一个节点,否则插入不了
		HeroNode temp = head;
		boolean flag = false; // flag标志添加的编号是否存在,默认为false
		while(true) {
			if(temp.next == null) {//说明temp已经在链表的最后
				System.out.println("链表无这东西");
				break; //
			} 
		if (temp.next.no == delheroNode.no) {//说明希望添加的heroNode的编号已然存在
				
				flag = true; //说明编号存在
				break;
			}
			temp = temp.next; //后移,遍历当前链表
		}
		//判断flag 的值
		if(flag) { //不能添加,说明编号存在
			 
			temp.next =temp.next.next;
					

		} else {
		
			System.out.println("无这个英雄不能修改"+delheroNode.toString());
		}
	}

5.修改单链表的数据

具体和上面两个差不多

public void update(HeroNode heroNode) {
		//因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助找到添加的位置
		//因为单链表,因为我们找的temp 是位于 添加位置的前一个节点,否则插入不了
		HeroNode temp = head;
		boolean flag = false; // flag标志添加的编号是否存在,默认为false
		while(true) {
			if(temp.next == null) {//说明temp已经在链表的最后
				break; //
			} 
		if (temp.next.no == heroNode.no) {//说明希望添加的heroNode的编号已然存在
				
				flag = true; //说明编号存在
				break;
			}
			temp = temp.next; //后移,遍历当前链表
		}
		//判断flag 的值
		if(flag) { //不能添加,说明编号存在
			 
			temp.next.no = heroNode.no;
			temp.next.name=heroNode.name;
			temp.next.nickName=heroNode.nickName;
					

		} else {
		
			System.out.println("无这个英雄不能修改"+heroNode.toString());
		}
	}
	

6.输出单链表

通过while循环做一个遍历

//显示链表[遍历]
	public void list() {
		//判断链表是否为空
		if(head.next == null) {
			System.out.println("链表为空");
			return;
		}
		//因为头节点,不能动,因此我们需要一个辅助变量来遍历
		HeroNode temp = head.next;
		while(true) {
			//判断是否到链表最后
			if(temp == null) {
				break;
			}
			//输出节点的信息
			System.out.println(temp);
			//将temp后移, 一定小心
			temp = temp.next;
		}
	}