链表
单链表介绍
链表的真实结构
结构分析
从结构图中可以分析出
- 链表是以节点的方式来存储值
- 每一个节点包含了值和next节点
- 链表的各个节点不一定是连续存储的
- 链表分为带头节点的链表和不带头节点的链表
链表的逻辑结构
单链表的代码实现
分析节点属性
- 数据属性(如姓名,大招技能等)
- 下一节点next(故其属性是一个节点!)
class Node {
public int no;
public String name;
public String big;
//注意node节点中next的属性!!!!
public Node next;
public Node(int no, String name, String big) {
this.no = no;
this.name = name;
this.big = big;
}
@Override
public String toString() {
return "Node{" +
"no=" + no +
", name='" + name + '\'' +
", big='" + big + '\'' +
'}';
}
}
添加元素的方法add()(顺序添加,只能插在链表的尾部)
- 通过死循环来遍历,要找一个临时的指针temp,来遍历整个链表,因为要找到最后一个节点,进行插值。
- 如果找到最后一个节点位置,则直接进行跳出循环进行插值
- 如果没有找到最后一个节点,则在循环中进行指针指向下一个节点的操作
//添加节点的方法,采用顺序插入法,将新的节点插到最后一个位置,故肯定是要遍历出最后一个节点,来存放这个数据
public void add(Node node) {
//由于头节点不能动,故要设置一个临时节点来遍历,从而找到最后一个节点
Node temp = head;
//通过死循环找出最后一个节点
while (true) {
if (temp.next == null) {
break;
}
//如果不是最后一个节点,就找下一个
temp = temp.next;
}
//找到最后一个节点之后,将新的插入节点赋值到最后一个节点上
temp.next = node;
}
添加元素的方法addByOrder()(可以判断no的值来排序)
通过以上图,当新的节点值为4时,通过temp指针判断要插入的位置。因为要按照顺序插入,需要两步:
- node.next=temp.next
- temp.next=node
//通过顺序加入
public void addByOrder(Node node) {
//还是要引入辅助变量
Node temp = head;
//此标记用来判断所添加的元素是否已经存在
boolean flag = false;
//遍历整个链表
while (true) {
if (temp.next == null) {
break;
}
//找到要插入节点的位置
if (temp.next.no > node.no) {
break;
} else if (temp.next.no == node.no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
System.out.println("准备插入的人编号【" + node.no + "】已存在");
} else {
//若可以插入,则将新的节点插入
node.next = temp.next;
temp.next = node;
}
}
删除节点的方法delete()
如图,想要删除一个节点步骤:
- 首先确定要删除节点的前一个位置即temp。
- 找到位置之后,只需要让temp.next=temp.next.next就可以实现删除节点的操作。
- 没有引用的节点,会被垃圾回收机制回收掉。
public void delete(int no){
Node temp=head;
boolean flag=false;
while (true){
//说明是一个空的链表
if(temp==null){
break;
}
if(temp.next.no==no){
//说明找到了
flag=true;
break;
}
temp=temp.next;
}
if(flag){
temp.next=temp.next.next;
System.out.println("编号为【"+no+"】的英雄删除成功!");
}else {
System.out.println("编号为【"+no+"】的英雄不存在!");
}
}
修改节点的方法update()
public void update(Node newNode){
Node temp=head;
//表示链表中是否存在该节点
boolean flag=false;
while(true){
if(temp==null){
break;
}
if(temp.no==newNode.no){
flag=true;
break;
}
temp=temp.next;
}
if(flag){
temp.name=newNode.name;
temp.big=newNode.big;
System.out.println("修改成功!");
}else {
System.out.println("没有找到编号为["+newNode.no+"]的节点");
}
}
显示元素的方法display()
- 首先判断链表是否为空,若为空,可以直接返回
- 通过死循环来遍历整个链表进行输出,如果找到最后一个节点,则跳出死循环
//显示链表中的节点,同是需要找一个;临时指针来遍历链表
public void display() {
//首先判断链表是否为空
if (head.next == null) {
return;
}
Node temp = head.next;
//遍历每一个链表
while (true) {
//如果下一个节点为空,说明已经找到了最后一个节点,可以退出
if (temp == null) {
break;
}
System.out.println(temp);
temp = temp.next;
}
}
代码测试
package com.njupt.List;
/**
* Creat with IntelliJ IDEA
*
* @Auther:倔强的加瓦
* @Date:2021/07/13/11:32
* @Description:
*/
public class LinkedListDemo {
public static void main(String[] args) {
Node node1 = new Node(1, "花木兰", "推推");
Node node2 = new Node(2, "张飞", "变大");
Node node3 = new Node(3, "牛魔", "起飞");
Node node4 = new Node(4, "鲁班", "等死");
SingList singList = new SingList();
System.out.println("使用有序插入:");
singList.add(node1);
singList.add(node2);
singList.add(node4);
singList.add(node3);
singList.display();
//测试修改英雄
Node node5 = new Node(4, "鲁班", "起飞升天");
singList.update(node5);
singList.display();
System.out.println("------删除-------");
singList.delete(1);
singList.display();
System.out.println("------删除-------");
SingList singList1 = new SingList();
System.out.println("使用无序插入:");
singList1.addByOrder(node1);
singList1.addByOrder(node2);
singList1.addByOrder(node4);
singList1.addByOrder(node3);
singList1.display();
}
}
//2创建链表来管理对象
class SingList {
//头节点不存放数据,并且不能动
private Node head = new Node(0, "", "");
//添加节点的方法,采用顺序插入法,将新的节点插到最后一个位置,故肯定是要遍历出最后一个节点,来存放这个数据
public void add(Node node) {
//由于头节点不能动,故要设置一个临时节点来遍历,从而找到最后一个节点
Node temp = head;
//通过死循环找出最后一个节点
while (true) {
if (temp.next == null) {
break;
}
//如果不是最后一个节点,就找下一个
temp = temp.next;
}
//找到最后一个节点之后,将新的插入节点赋值到最后一个节点上
temp.next = node;
}
//通过顺序加入
public void addByOrder(Node node) {
//还是要引入辅助变量
Node temp = head;
//此标记用来判断所添加的元素是否已经存在
boolean flag = false;
//遍历整个链表
while (true) {
if (temp.next == null) {
break;
}
if (temp.next.no > node.no) {
break;
} else if (temp.next.no == node.no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
System.out.println("准备插入的人编号【" + node.no + "】已存在");
} else {
//若可以插入,则将新的节点插入
node.next = temp.next;
temp.next = node;
}
}
//修改节点信息的方法
public void update(Node newNode){
Node temp=head;
//表示链表中是否存在该节点
boolean flag=false;
while(true){
if(temp==null){
break;
}
if(temp.no==newNode.no){
flag=true;
break;
}
temp=temp.next;
}
if(flag){
temp.name=newNode.name;
temp.big=newNode.big;
System.out.println("修改成功!");
}else {
System.out.println("没有找到编号为["+newNode.no+"]的节点");
}
}
public void delete(int no){
Node temp=head;
boolean flag=false;
while (true){
//说明是一个空的链表
if(temp==null){
break;
}
if(temp.next.no==no){
//说明找到了
flag=true;
break;
}
temp=temp.next;
}
if(flag){
temp.next=temp.next.next;
System.out.println("编号为【"+no+"】的英雄删除成功!");
}else {
System.out.println("编号为【"+no+"】的英雄不存在!");
}
}
//显示链表中的节点,同是需要找一个;临时指针来遍历链表
public void display() {
//首先判断链表是否为空
if (head.next == null) {
return;
}
Node temp = head.next;
//遍历每一个链表
while (true) {
//如果下一个节点为空,说明已经找到了最后一个节点,可以退出
if (temp == null) {
break;
}
System.out.println(temp);
temp = temp.next;
}
}
}
//1创建节点对象
class Node {
public int no;
public String name;
public String big;
public Node next;
public Node(int no, String name, String big) {
this.no = no;
this.name = name;
this.big = big;
}
@Override
public String toString() {
return "Node{" +
"no=" + no +
", name='" + name + '\'' +
", big='" + big + '\'' +
'}';
}
}