单链表
单链表(带头链表)的逻辑结构示意图
单链表的应用实例
使用带 head 头的单向链表实现:对水浒英雄排行榜管理,完成对英雄人物的增删改查操作。
(1)第一种方法添加英雄时,直接添加到链表的尾部。
思路分析示意图:
(2)第二种方式添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)
思路示意图:
(3)修改节点功能
思路分析:
① 先找到该节点,通过遍历
② temp.name = newHeroNode.name; temp.nickname = newHeroNode.nickname;
(4)删除节点功能
思路分析:
(5)代码实现
1 public class SingleLinkedListDemo {
2
3 public static void main(String[] args) {
4 // 测试
5 // 先创建节点
6 HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
7 HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
8 HeroNode hero3 = new HeroNode(3, "吴用", "智多星");
9 HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");
10
11 // 创建链表
12 SingleLinkedList list = new SingleLinkedList();
13
14 // 加入
15 list.add(hero1);
16 list.add(hero2);
17 list.add(hero3);
18 list.add(hero4);
19
20 // 显示
21 list.list();
22
23 // 修改
24 HeroNode heroNode = new HeroNode(2, "小卢", "玉麒麟~~");
25 list.update(heroNode);
26
27 System.out.println("修改后的链表-----");
28 list.list();
29
30 // 删除节点
31 list.del(1);
32 System.out.println("删除后的链表-----");
33 list.list();
34
35 }
36
37 }
38
39 // 定义 SingleLinkedList ,管理英雄
40 class SingleLinkedList {
41 // 先初始化一个头节点,头节点不要动,不存放具体的数据
42 private HeroNode head = new HeroNode(0, "", "");
43
44 // 添加节点到单向链表
45 // 当不考虑编号顺序时,
46 // 1.找到当前链表的最后节点
47 // 2.将最后这个节点的 next 指向新的节点
48 public void add(HeroNode heroNode) {
49
50 // 因为head节点不能动,因此我们需要一个辅助指针 temp
51 HeroNode temp = head;
52 // 遍历
53 while (true) {
54 // 找到链表的最后
55 if (temp.next == null) {
56 break;
57 }
58 // 如果没有找到最后,将 temp 后移
59 temp = temp.next;
60 }
61
62 // 当退出 while 循环时,temp 就执行了链表的最后
63 // 将最后这个节点的 next指向新的节点
64 temp.next = heroNode;
65 }
66
67 // 修改节点的信息,根据 no 编号来修改,即no编号不能改
68 // 根据newHeroNode 的 no 来修改即可
69 public void update(HeroNode newHeroNode) {
70 // 判断是否为空
71 if (head.next == null) {
72 System.out.println("链表为空");
73 return;
74 }
75 // 找到需要修改的节点,根据 no 编号
76 // 定义一个辅助变量
77 HeroNode temp = head.next;
78 boolean flag = false; // 表示是否找到该节点
79 while (true) {
80 if (temp == null) {
81 break; // 已经遍历完
82 }
83 if (temp.no == newHeroNode.no) {
84 flag = true;
85 break;
86 }
87
88 temp = temp.next;
89 }
90
91 // 根据 flag,判断是否找到要修改的节点
92 if (flag) {
93 temp.name = newHeroNode.name;
94 temp.nickname = newHeroNode.nickname;
95 } else {
96 System.out.printf("没有找到编号%d的节点,不能修改\n", newHeroNode.no);
97 }
98 }
99
100 // 删除节点
101 // head 不能动,需要一个辅助节点,找到待删除节点的前一个节点
102 // 比较时,就是 temp.next.no 和需要删除的节点 no 比较
103 public void del(int no) {
104 HeroNode temp = head;
105 boolean flag = false; // 标志是否找到待删除节点
106 while (true) {
107 if (temp.next == null) {
108 break;
109 }
110 if (temp.next.no == no) {
111 // 找到了待删除节点的前一个节点 temp
112 flag = true;
113 break;
114 }
115 temp = temp.next; // temp 后移
116 }
117 // 判断是否找到
118 if (flag) {
119 // 找到,可以删除
120 temp.next = temp.next.next;
121 } else {
122 System.out.printf("要删除的%d节点不存在", no);
123 }
124 }
125
126 // 显示链表【遍历】
127 public void list() {
128 // 判断链表是否为空
129 if (head.next == null) {
130 System.out.println("链表为空");
131 return;
132 }
133
134 // 因为头节点不能动,需要辅助变量来遍历
135 HeroNode temp = head.next;
136 while (true) {
137 // 判断是否到链表最后
138 if (temp == null) {
139 break;
140 }
141 // 输出节点信息
142 System.out.println(temp);
143 // 将 next 后移
144 temp = temp.next;
145 }
146 }
147
148 // 第二种方式在添加英雄时,根据排名将英雄插入到指定位置
149 // 如果有这个排名,则添加失败,并给出提示
150 public void addByorder(HeroNode heroNode) {
151 // 因为头节点不能动,因此需要通过一个辅助指针(变量)来帮助找到添加的位置
152 // 因为单链表,因为找到的 temp 是位于添加位置的前一个节点,否则无法插入
153 HeroNode temp = head;
154 boolean flag = false; // 标志添加的编号是否存在,默认为false
155 while (true) {
156 if (temp.next == null) { // 说明 temp 以及在链表最后
157 break;
158 }
159 if (temp.next.no > heroNode.no) { // 找到位置,就在temp的后面插入
160 break;
161 } else if (temp.next.no == heroNode.no) {
162 flag = true; // 编号存在
163 break;
164 }
165 temp = temp.next; // 后移,遍历当前链表
166 }
167
168 // 判断 flag 的值
169 if (flag) {
170 System.out.printf("准备插入的英雄的编号%d已经存在,不能加入\n", heroNode.no);
171 } else {
172 // 插入到链表中
173 heroNode.next = temp.next;
174 temp.next = heroNode;
175 }
176
177 }
178
179 }
180
181 // 定义 HeroNode,每个 HeroNode 对象就是一个节点
182 class HeroNode {
183 public int no;
184 public String name;
185 public String nickname;
186 public HeroNode next; // 指向下一个节点
187
188 // 构造器
189 public HeroNode(int no, String name, String nickname) {
190 this.no = no;
191 this.name = name;
192 this.nickname = nickname;
193 }
194
195 @Override
196 public String toString() {
197 return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
198 }
199
200 }