目录
1.带头单链表内存中的存储
1、链表是以节点的方式来存储,是链式存储
2、每个节点包含 data 域, next 域:指向下一个节点.
3、如图:发现链表的各个节点不一定是连续存储.
4、链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定
2.带头单链表逻辑结构
逻辑上看就是,根据头连续,但是内存中的排布则未必连续存储 。
3.结构示例
public class SingleLinkedNode {
private int num; //编号
private String name; //姓名
private int age; //年龄
private SingleLinkedNode next; //指向下一个元素
...
}
4.代码示例
4.1 节点类
public class SingleLinkedNode {
private int num; //编号
private String name; //姓名
private int age; //年龄
private SingleLinkedNode next; //指向下一个元素
public SingleLinkedNode(int num, String name, int age) {
this.num = num;
this.name = name;
this.age = age;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public SingleLinkedNode getNext() {
return next;
}
public void setNext(SingleLinkedNode next) {
this.next = next;
}
@Override
public String toString() {
return "SingleLinkedList{" +
"num=" + num +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
4.2 链表类 包含增删改查等操作函数
class SingleLinkedList{
//设置一个头节点
private SingleLinkedNode head = new SingleLinkedNode(0,null,0);
public SingleLinkedNode getHead() {
return head;
}
/**
* 根据编号查询,编号是唯一的,不允许重复
* @param num
* @return
*/
public SingleLinkedNode queryByNum(int num){
//使用temp来作为遍历操作的指针
SingleLinkedNode temp = head;
//判空
if (temp.getNext() == null){
System.out.println("this link is null");
return null;
}
while (true){
if (temp.getNext() == null){
System.out.println("can not find this node");
return null;
}
if (temp.getNext().getNum() == num){
System.out.println("success find this num");
return temp.getNext();
}
temp = temp.getNext();
}
}
/**
* 根据姓名查询,返回数组
* @param name
* @return
*/
public ArrayList<SingleLinkedNode> queryByName(String name){
//姓名有可能重复,所以返回一个数组
ArrayList<SingleLinkedNode> singleLinkedNodeArrayList = new ArrayList<>();
//计数
int count = 0;
//使用temp来作为遍历操作的指针
SingleLinkedNode temp = head;
//判空
if (temp.getNext() == null){
System.out.println("this link is null");
return null;
}
while (true){
if (temp.getNext() == null){
System.out.println("查找结束");
break;
}
if (temp.getNext().getName() == name){
count++;
System.out.println("找到了,这是第" + count + "个节点");
singleLinkedNodeArrayList.add(temp.getNext());
}
temp = temp.getNext();
}
return singleLinkedNodeArrayList;
}
/**
* 尾插法添加元素
* @return
*/
public void add(SingleLinkedNode singleLinkedNode){
//因为head不能动,所以设置一个temp,用来遍历
SingleLinkedNode temp = head;
while (true){
if (temp.getNext() != null){
temp = temp.getNext();
}else {
temp.setNext(singleLinkedNode);
break;
}
}
}
/**
* 升序插入 头插法
* @param singleLinkedNode
*/
public void addByOrder(SingleLinkedNode singleLinkedNode) {
// 因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助找到添加的位置
// 因为单链表,因为我们找的temp 是位于 添加位置的前一个节点,否则插入不了
SingleLinkedNode temp = head;
boolean flag = false;// flag标志添加的编号是否存在,默认为false
while(true) {
if(temp.getNext() == null) break;
if(temp.getNext().getNum() > singleLinkedNode.getNum())
// 位置找到,就在 temp后面
// 因为 它满足了 按顺序 ,所以可以插入
break;
if(temp.getNext().getNum() == singleLinkedNode.getNum()) {
// 已经存在改排行的编号(不可重复)
flag = true;
break;
}
// 没满足以上,后移下一次节点继续找
temp = temp.getNext();
}
// 对 flag 进行判断
if(flag)
// 不能添加,说明编号已经存在
System.out.printf("准备插入的英雄的编号 %d 已经存在了, 不能加入\n", singleLinkedNode.getNum());
else {
// 插入到链表中,temp的后面
singleLinkedNode.setNext(temp.getNext());// 我后面的是6号,现在你后面是6号
temp.setNext(singleLinkedNode);// 我后面是你
}
}
/**
* 根据编号删除
* @return
*/
public boolean deleteByNum(int num){
SingleLinkedNode temp =head;
boolean flag = false;
while (true){
if (temp.getNext() == null){
System.out.println("没有这个元素");
break;
}
if (temp.getNext().getNum() == num){
//判断是否是末尾
if (temp.getNext().getNext() == null){
temp.setNext(null);
}else {
temp.setNext(temp.getNext().getNext());
}
System.out.println("元素找到了,已经删除");
flag = true;
break;
}
temp = temp.getNext();
}
return flag;
}
/**
* 根据姓名删除,删除所有姓名为name的节点
* @param name
* @return
*/
public boolean deleteByName(String name){
SingleLinkedNode temp = head;
boolean flag = true;
int count = 0;
//判空
if (null == temp.getNext()){
System.out.println("该链表为空");
return false;
}
while (true){
//遍历删除后,判断有没有删除
if (temp.getNext() == null){
if (count == 0){
System.out.println("链表中没有找到");
flag = false;
}else {
System.out.println("遍历完成,已经删除所有符合条件的节点");
}
break;
}
if (name.equals(temp.getNext().getName())){
count ++;
//判断是否是最后一个节点
if (null == temp.getNext().getNext()){
System.out.println("已经删除节点" + temp.getNext().getNum());
temp.setNext(null);
break;
}else {
System.out.println("已经删除节点" + temp.getNext().getNum());
temp.setNext(temp.getNext().getNext());
}
}
temp = temp.getNext();
}
System.out.println("此时已经删除的节点数为:" + count);
return flag;
}
/**
* 遍历链表
*/
public void list(){
//因为head不能动,所以设置一个temp,用来遍历
SingleLinkedNode temp = head;
while (true){
if (temp.getNext() != null){
System.out.println(temp.getNext());
}else {
break;
}
temp = temp.getNext();
}
}
}
4.3 测试类
import java.util.ArrayList;
public class SingleLinkedList_Test {
public static void main(String[] args) {
SingleLinkedList singleLinkedList = new SingleLinkedList();
//添加
singleLinkedList.add(new SingleLinkedNode(1,"曹操",20));
singleLinkedList.add(new SingleLinkedNode(2,"吕布",20));
singleLinkedList.add(new SingleLinkedNode(3,"孙策",20));
singleLinkedList.add(new SingleLinkedNode(4,"赵云",20));
singleLinkedList.addByOrder(new SingleLinkedNode(8,"张飞",20));
singleLinkedList.addByOrder(new SingleLinkedNode(5,"貂蝉",20));
singleLinkedList.addByOrder(new SingleLinkedNode(7,"刘备",20));
singleLinkedList.addByOrder(new SingleLinkedNode(6,"马超",20));
singleLinkedList.addByOrder(new SingleLinkedNode(9,"马超",20));
//显示
singleLinkedList.list();
//queryByNum
SingleLinkedNode singleLinkedNode = singleLinkedList.queryByNum(8);
System.out.println(singleLinkedNode);
for (int i = 1; i <= 9; i++){
SingleLinkedNode singleLinkedNode1 = singleLinkedList.queryByNum(i);
System.out.println(singleLinkedNode1);
}
//queryByName
ArrayList<SingleLinkedNode> singleLinkedNodeArrayList = singleLinkedList.queryByName("马超");
singleLinkedNodeArrayList.stream().forEach(System.out::println);
//deleteByNum
// System.out.println("##########################");
// System.out.println("执行删除操作");
// boolean b = singleLinkedList.deleteByNum(1);
// singleLinkedList.list();
//deleteByName
System.out.println("##########################");
System.out.println("执行删除操作");
boolean b = singleLinkedList.deleteByName("马超");
singleLinkedList.list();
}
}
4.4 结果显示
"C:\Program Files\Java8\Java8_144\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.3.2\lib\idea_rt.jar=54496:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.3.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java8\Java8_144\jre\lib\charsets.jar;C:\Program Files\Java8\Java8_144\jre\lib\deploy.jar;C:\Program Files\Java8\Java8_144\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java8\Java8_144\jre\lib\ext\cldrdata.jar;C:\Program Files\Java8\Java8_144\jre\lib\ext\dnsns.jar;C:\Program Files\Java8\Java8_144\jre\lib\ext\jaccess.jar;C:\Program Files\Java8\Java8_144\jre\lib\ext\jfxrt.jar;C:\Program Files\Java8\Java8_144\jre\lib\ext\localedata.jar;C:\Program Files\Java8\Java8_144\jre\lib\ext\nashorn.jar;C:\Program Files\Java8\Java8_144\jre\lib\ext\sunec.jar;C:\Program Files\Java8\Java8_144\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java8\Java8_144\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java8\Java8_144\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java8\Java8_144\jre\lib\ext\zipfs.jar;C:\Program Files\Java8\Java8_144\jre\lib\javaws.jar;C:\Program Files\Java8\Java8_144\jre\lib\jce.jar;C:\Program Files\Java8\Java8_144\jre\lib\jfr.jar;C:\Program Files\Java8\Java8_144\jre\lib\jfxswt.jar;C:\Program Files\Java8\Java8_144\jre\lib\jsse.jar;C:\Program Files\Java8\Java8_144\jre\lib\management-agent.jar;C:\Program Files\Java8\Java8_144\jre\lib\plugin.jar;C:\Program Files\Java8\Java8_144\jre\lib\resources.jar;C:\Program Files\Java8\Java8_144\jre\lib\rt.jar;D:\JavaTest\DS_Test\out\production\DS_Test" com.djh.SingleLinkedList.SingleLinkedList_Test
SingleLinkedList{num=1, name='曹操', age=20}
SingleLinkedList{num=2, name='吕布', age=20}
SingleLinkedList{num=3, name='孙策', age=20}
SingleLinkedList{num=4, name='赵云', age=20}
SingleLinkedList{num=5, name='貂蝉', age=20}
SingleLinkedList{num=6, name='马超', age=20}
SingleLinkedList{num=7, name='刘备', age=20}
SingleLinkedList{num=8, name='张飞', age=20}
SingleLinkedList{num=9, name='马超', age=20}
success find this num
SingleLinkedList{num=8, name='张飞', age=20}
success find this num
SingleLinkedList{num=1, name='曹操', age=20}
success find this num
SingleLinkedList{num=2, name='吕布', age=20}
success find this num
SingleLinkedList{num=3, name='孙策', age=20}
success find this num
SingleLinkedList{num=4, name='赵云', age=20}
success find this num
SingleLinkedList{num=5, name='貂蝉', age=20}
success find this num
SingleLinkedList{num=6, name='马超', age=20}
success find this num
SingleLinkedList{num=7, name='刘备', age=20}
success find this num
SingleLinkedList{num=8, name='张飞', age=20}
success find this num
SingleLinkedList{num=9, name='马超', age=20}
找到了,这是第1个节点
找到了,这是第2个节点
查找结束
SingleLinkedList{num=6, name='马超', age=20}
SingleLinkedList{num=9, name='马超', age=20}
##########################
执行删除操作
已经删除节点6
已经删除节点9
此时已经删除的节点数为:2
SingleLinkedList{num=1, name='曹操', age=20}
SingleLinkedList{num=2, name='吕布', age=20}
SingleLinkedList{num=3, name='孙策', age=20}
SingleLinkedList{num=4, name='赵云', age=20}
SingleLinkedList{num=5, name='貂蝉', age=20}
SingleLinkedList{num=7, name='刘备', age=20}
SingleLinkedList{num=8, name='张飞', age=20}
Process finished with exit code 0