单链表
如果当我们有一些无序的数据,需要在内存当中进行排序我们可以使用单链表的方式进行处理
package 单链表;
/**
* @Date 2022/1/21
* @Author Acer
*/
public class demo {
public static void main(String[] args) {
HeroNode heroNode1 = new HeroNode(1, "宋江", "及时雨");
HeroNode heroNode2 = new HeroNode(2,"卢俊义","玉麒麟");
HeroNode heroNode3 = new HeroNode(3,"吴用","智多星");
SingleLinkedList singleLinkedList=new SingleLinkedList();
// singleLinkedList.add(heroNode1);
// singleLinkedList.add(heroNode2);
// singleLinkedList.add(heroNode3);
// singleLinkedList.list();
singleLinkedList.add2(heroNode1);
singleLinkedList.add2(heroNode3);
singleLinkedList.add2(heroNode2);
singleLinkedList.add2(heroNode2);
singleLinkedList.list();
HeroNode heroNode4 = new HeroNode(2,"卢俊义1","玉麒麟");
singleLinkedList.update(heroNode4);
System.out.println("修改之后");
singleLinkedList.list();
}
}
//定义一个单链表来管理我们的英雄
class SingleLinkedList {
//初始化头结点,不要动
private HeroNode head = new HeroNode(0, "", "");
//添加结点
//1、找到当前结点最后的结点;2、将最后的这个节点的next指向新的节点
public void add(HeroNode headNode) {
//因为头节点不等动,因此需要一个辅助接点
HeroNode temp = head;
//遍历找到最后
while (true) {
//是最后一个
if (temp.next == null) {
break;
}
//不是最后一个
temp = temp.next;
}
temp.next = headNode;
}
/*
添加结点2
需要排序
*/
public void add2(HeroNode headNode) {
//因为头节点不等动,因此需要一个辅助接点
HeroNode temp = head;
boolean flag=false;//用于表示添加的编号是否存在
while (true){
if(temp.next==null){
break;
}
if(temp.next.no>headNode.no){
break;
}else if(temp.next.no==headNode.no){
flag=true;
break;
}
temp=temp.next;
}
if(flag){
System.out.println(headNode.no+"当前的英雄已存在");
}else{
headNode.next=temp.next;
temp.next=headNode;
}
}
//修改
public void update(HeroNode newHeroNode){
HeroNode temp=head;
boolean falg=false;
while (true){
if(temp.next==null){
break;
}
if(temp.no== newHeroNode.no){
falg=true;
break;
}
temp=temp.next;
}
if(falg){
temp.name=newHeroNode.name;
temp.nickname=newHeroNode.nickname;
}else{
System.out.println("当前信息不存在");
}
}
//删除
public void del(int no) {
HeroNode temp = head;
boolean flag = false;
while (true) {
if (temp.next == null) {
break;
}
if (temp.next.no == no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.next = temp.next.next;
} else {
System.out.println("要删除的节点不存在");
}
}
/**
* 遍历链表
*/
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.next;
}
}
}
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;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
通过LinkedList实现数据的排序
1、第一个add是,可以实现:添加到结点最后无排序
2、第二个add2是可以实现:随机插入一条数据,判断有无存在重复,并可以有序的排列数据
重点:都需要一个辅助的集合帮助通过while循环判断实现数据的添加和排序
思路如下
LinkedList链表
定义:
1、链表是以节点分方式来储存
2、每个节点包含data域和next域指向下一个节点
3、链表的各个节点不一定是连续存放的
4、链表分带头结点和没有头结点的,根据实际情况需求来
创建示意图:
头结点:不存放任何数据;作用:表示单链表的头。
思路1:添加到结点最后无排序
因为头部的结点不能动所以要定义一个辅助结点帮助我们添加
新建一个头部并并赋给temp
通过while循环判断,第一种情况当temp的next属性为空的时候直接跳出循环(因为这是最后一个结点)所以如果不是空就将其赋给temp在走一遍直到最后一个跳出;结束循环后将新的结点添加给上一个结点的最后一个next属性
思路2:随机添加到结点并且排序
因为头部的结点不能动所以要定义一个辅助结点帮助我们添加
新建一个头部并并赋给temp,在创建怡和falg判断是否已存在此结点;
通过while循环判断,第一种情况当temp的next属性为空的时候直接跳出循环(因为这是最后一个结点)第二种情况当新加入的结点的no值小于当前结点里面的next(指向下一个结点)的no,说明新的结点就在它的前面,第三种情况丁当前的结点的no等于当前任意一个next中的no时候说明都已存在直接跳出。Falg等于true;循环做完如果没有在将这个nex赋给temp在来一次直到符合条件跳出。
最后判断,当falg等于true说明重复,当为false则将先新节点的next改为它前面的那个next,然后将前面的next改为这个新接点;
思路3:修改
因为头部的结点不能动所以要定义一个辅助结点帮助我们添加
新建一个头部并并赋给temp,falg=false;
通过while循环判断,第一种情况当temp的next属性为空的时候直接跳出循环(因为这是最后一个结点)第二种情况如果当前定义temp的no等于传入的结点的no就将falg改为true,一遍循环如果为没有找到走下一次;判断如果当falg是true则将新的结点属性赋给temp的结点,否则及时当前数组没有这个数据;
思路4:删除
因为头部的结点不能动所以要定义一个辅助结点帮助我们添加
新建一个头部并并赋给temp,falg=false;
通过while循环判断,第一种情况当temp的next属性为空的时候直接跳出循环(因为这是最后一个结点)第二种情况如果当前定义temp的next的no等于传入的的no就将falg改为true,一遍循环如果为没有找到走下一次;完成之后将会得到要删除结点的前一个结点。则判断如果当falg是true则将要删除前结点的的next值等于这个要删除前结点的的next的next,否则及时当前数组没有这个数据;
双链表
package 双向链表;
/**
* @Date 2022/1/22
* @Author Acer
*/
public class demo {
public static void main(String[] args) {
HeroNode2 heroNode1 = new HeroNode2(1, "宋江", "及时雨");
HeroNode2 heroNode2 = new HeroNode2(2, "卢俊义", "玉麒麟");
HeroNode2 heroNode3 = new HeroNode2(3, "吴用", "智多星");
HeroNode2 heroNode5 = new HeroNode2(5, "吴用", "智多星");
System.out.println("测试双向链表:");
DoubleLinkedList doubleLinkedList=new DoubleLinkedList();
doubleLinkedList.add2(heroNode5);
doubleLinkedList.add2(heroNode1);
doubleLinkedList.add2(heroNode2);
doubleLinkedList.add2(heroNode3);
doubleLinkedList.list();
HeroNode2 heroNode4 = new HeroNode2(3, "吴用1", "智多星1");
doubleLinkedList.update(heroNode4);
System.out.println("编辑之后:");
doubleLinkedList.list();
doubleLinkedList.del(5);
System.out.println("删除之后:");
doubleLinkedList.list();
}
}
class DoubleLinkedList {
private HeroNode2 head = new HeroNode2(0, "", "");
//返回节点
public HeroNode2 getHead() {
return head;
}
//遍历双向列表
public void list() {
if (head.next == null) {
System.out.println("双链表为空");
}
HeroNode2 temp = head;
while (true) {
if (temp.next == null) {
break;
}
System.out.println(temp.next);
temp = temp.next;
}
}
//添加(添加到最后)
public void add(HeroNode2 newHeroNode) {
HeroNode2 temp = head;
while (true) {
if (temp.next == null) {
break;
}
temp = temp.next;
}
temp.next = newHeroNode;
newHeroNode.pre = temp;
}
//添加(按照顺序)
public void add2(HeroNode2 headNode) {
//因为头节点不等动,因此需要一个辅助接点
HeroNode2 temp = head;
boolean flag = false;//用于表示添加的编号是否存在
while (true) {
if (temp.next == null) {
break;
}
if (temp.next.no > headNode.no) {
break;
} else if (temp.next.no == headNode.no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
System.out.println(headNode.no + "当前的英雄已存在");
} else {
headNode.next=temp.next;
temp.next=headNode;
headNode.pre=temp.next.pre;
temp.next.pre=headNode;
}
}
//修改
public void update(HeroNode2 newHeroNode) {
if (head.next == null) {
System.out.println("链表为空");
return;
}
HeroNode2 temp = head;
boolean flag = false;
while (true) {
if (temp.next == null) {
break;
}
if (temp.next.no == newHeroNode.no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.next.name = newHeroNode.name;
temp.next.nickname = newHeroNode.nickname;
} else {
System.out.println("没有这结点");
}
}
//删除
public void del(int no) {
if (head.next == null) {
System.out.println("链表为空");
return;
}
HeroNode2 temp = head.next;
boolean flag = false;
while (true) {
if (temp == null) {
break;
}
if (temp.no == no) {
flag = true;
break;
}
temp = temp.next;
}
if (flag) {
temp.pre.next = temp.next;
//代码有风险(需要注意当前删除的节点的是否为最后一个,避免空指针)
if (temp.next != null) {
temp.next.pre = temp.pre;
}
} else {
System.out.println("结点不存在");
}
}
}
//创建双向链表的类
class HeroNode2 {
int no;
String name;
String nickname;
HeroNode2 next;//指向下一个节点
HeroNode2 pre;//指向前一个结点
public HeroNode2(int no, String name, String nickname) {
this.no = no;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "HeroNode{" +
"no=" + no +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
思路
双向链表的修改与单向链表一直,在添加方面比单链表加一个指向上一个列表的属性,在按顺序排序的时候需要在先给next赋值之后才可以给上一节per辅值;
在删除方面不需要接住删除结点的上一个结点,可以知己根据当前的结点进行处理;
双链表和单链表的区别就是在每一个属性上面记上指向上一个结点的属性。