链表分两种链表,一种是带头节点,一种是不带头节点的,一个节点分为data域,next域,next域指向下一个节点的地址,一次来链接所有节点。
特点:链式存储,它的每个节点在内存中并不是一定连续的。
链表是有序的列表,但是它在内存中是存储的实际结构如下图:
使用带head头的单向链表实现增删改查:
单链表的创建示意图(添加),显示单向链表的分析:
头节点不存放数据,主要作用链接链表,如下图
思路分析:
添加(创建)
1.先创建一个head头节点,作用就是表示单链表的头
2.后面我们每添加一个节点,就直接加入到 链表的最后遍历:
public class SingleLinkedListDemo {public static void main(String[] args) {//进行测试//创建节点HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");HeroNode hero3 = new HeroNode(3, "吴用", "智多星");HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");//创建一个链表SingleLinkedList singleLinkedList = new SingleLinkedList();//加入singleLinkedList.add(hero1);singleLinkedList.add(hero2);singleLinkedList.add(hero3);singleLinkedList.add(hero4);singleLinkedList.list();}
}// 定义singleLinkedList 管理我们的单链表
class SingleLinkedList {//先初始化一个头节点,头节点不要动,不存放具体的数据private HeroNode head = new HeroNode(0, "", "");//添加节点到单向链表//思路,当不考虑编号顺序时// 1. 找到当前链表的最后节点// 2. 将最后这个节点的next指向新的节点public void add(HeroNode heroNode) {//因为head节点不能动,因此我们需要一个辅助遍历 tempHeroNode temp = head;//遍历链表,找到最后while (true) {if ( == null) {break;}//如果没有找到最后,将将temp后移temp = ;}//当退出while循环时,temp就指向了链表的最后//当退出while循环时,temp就指向了链表的最后 = heroNode;}//显示链表[遍历]public void list() {//判断链表是否为空if ( == null) {System.out.println("链表为空");return;}//因为头节点,不能动,因此我们需要一个辅助变量来遍历HeroNode temp = ;while (true) {//判断是否到链表最后if (temp == null) {break;}//输出节点的信息System.out.println(temp);//将temp后移,一定小心temp = ;}}
}//定义HeroNode ,每个HeroNode 对象就是一个节点
class HeroNode {public int no;public String name;public String nickname;public HeroNode next;public HeroNode(int no, String name, String nickname) { = no;this.name = name;this.nickname = nickname;}@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + ''' +", nickname='" + nickname;}
}
输出:
HeroNode{no=1, name='宋江', nickname='及时雨'
HeroNode{no=2, name='卢俊义', nickname='玉麒麟'
HeroNode{no=3, name='吴用', nickname='智多星'
HeroNode{no=4, name='林冲', nickname='豹子头'
这就是一个简单的添加链表节点的操作,但是上面这种方法添加节点,有缺陷,当不考虑编号顺序时,是可以这么做,就按照我们代码的执行顺序添加没问题,但是按照每个对象的编号顺序就做不到了。
什么意思呢?就是按照我们的HeroNode的no编号这个字段的大小来添加,一般是按顺序从小到大。
需要按照编号的顺序添加
1.首先找到新添加的节点的位置,是通过辅助变量(指针)通过遍历来搞定
2.新的节点next
3.将=新的节点
我们在上面的代码新增一个方法:
//按编号排序添加节点
public void addByOrder(HeroNode heroNode) {//因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助找到添加的位置//因为单链表,因为我们找的temp 是位于 添加位置的前一个节点,否则插入不了HeroNode temp = head;boolean flag = false;//标志添加的编号是否存在,默认为falsewhile (true) {if ( == null) {//说明temp已经在链表的最后break;}if ( > ) {//位置找到,就在temp的后面插入break;} else if ( == ) {//说明希望添加的heroNode的编号已然存在flag = true;//说明编号存在break;}temp = ;//后移,遍历当前链表}//判断flag 的值if (flag) {//不能添加,说明编号存在System.out.printf("准备插入的节点的编号 %d 已经存在了,不能加入了n", );} else {//插入到链表中,temp的后面 = ; = heroNode;}
}
main方法里面测试一下
//按编号no顺序添加
singleLinkedList.addByOrder(hero1);
singleLinkedList.addByOrder(hero3);
singleLinkedList.addByOrder(hero4);
singleLinkedList.addByOrder(hero2);
singleLinkedList.list();
输出
HeroNode{no=1, name='宋江', nickname='及时雨'
HeroNode{no=2, name='卢俊义', nickname='玉麒麟'
HeroNode{no=3, name='吴用', nickname='智多星'
HeroNode{no=4, name='林冲', nickname='豹子头'
我们添加的顺序是1 3 4 2,输出是按顺序的1 2 3 4
还是用我们原来上面的代码新增一个update的方法。
//修改节点的信息,根据no编号来修改,即no编号不能改。
//1. 根据 newHeroNode 的 no 来修改即可
public void update(HeroNode newHeroNode) {//判断是否为空if ( == null) {System.out.println("链表为空~");return;}//找到需要修改的节点,根据no编号//定义一个辅助变量HeroNode temp = ;boolean flag = false;//表示是否找到该节点while (true) {if (temp == null) {break;//已经遍历完链表}if ( == ) {//找到flag = true;break;}temp = ;}//根据flag 判断是否找到要修改的节点if (flag) {temp.name = newHeroNode.name;temp.nickname = newHeroNode.nickname;} else {//没有找到System.out.printf("没有找到 编号 %d 的节点,不能修改n", );}
}
main方法测试一下
//按编号no顺序添加
singleLinkedList.addByOrder(hero1);
singleLinkedList.addByOrder(hero3);
singleLinkedList.addByOrder(hero4);
singleLinkedList.addByOrder(hero2);System.out.println("修改前");
singleLinkedList.list();
//测试修改节点的代码
HeroNode newHeroNode = new HeroNode(2, "小卢", "玉麒麟~~");
singleLinkedList.update(newHeroNode);
System.out.println("修改后");
singleLinkedList.list();
结果输出:
修改前
HeroNode{no=1, name='宋江', nickname='及时雨'
HeroNode{no=2, name='卢俊义', nickname='玉麒麟'
HeroNode{no=3, name='吴用', nickname='智多星'
HeroNode{no=4, name='林冲', nickname='豹子头'
修改后
HeroNode{no=1, name='宋江', nickname='及时雨'
HeroNode{no=2, name='小卢', nickname='玉麒麟~~'
HeroNode{no=3, name='吴用', nickname='智多星'
HeroNode{no=4, name='林冲', nickname='豹子头'
结果是修改成功了。
从单链表中删除一个节点的思路
1.我们先找到需要删除的这个节点的前一个节点temp。
3.被删除的节点,将不会有其它引用指向,会被垃圾回收机制
代码:
//删除节点
//思路
//1.head 不能动,因此我们需要一个temp辅助节点找到待删除节点的前一个节点
//2.说明我们在比较时,是 和 需要删除的节点的no比较
public void del(int no) {HeroNode temp = head;boolean flag = false;//标志是否找到待删除节点的while (true) {if ( == null) {break;}if ( == no) {//找到的待删除节点的前一个节点tempflag = true;break;}temp = ;//temp后移,遍历}if (flag) {//找到//可以删除 = ;} else {System.out.printf("要删除的 %d 节点不存在n", no);}
}
main方法测试
//按编号no顺序添加
singleLinkedList.addByOrder(hero1);
singleLinkedList.addByOrder(hero3);
singleLinkedList.addByOrder(hero4);
singleLinkedList.addByOrder(hero2);//删除一个节点
singleLinkedList.del(1);
system.out.println("删除后的链表情况");
singleLinkedList.list();
输出:
删除后的链表情况
HeroNode{no=2, name='卢俊义', nickname='玉麒麟'
HeroNode{no=3, name='吴用', nickname='智多星'
HeroNode{no=4, name='林冲', nickname='豹子头'
我们确实看到有一个节点被删掉了。
本文发布于:2024-01-30 18:20:03,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170661000521924.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |