一、链表的介绍
- 链表是数据结构之一,其中的数据呈线性排列。
- 在链表中,数据的添加和删除都较为方便, 但是访问比较耗费时间。
- 每一个结点都包含了数据域和指针域(指向下一个结点的指针)。
- 链表的结构是链式的,但是内存不是连续的(如下图)
- 因为数据都是分散存储的,所以如果想要访问数据,只能从第1个数据开始,顺着指针的指向一一往下访问(这便是顺序访问)
- 除了单向链表还有双向链表和循环链表,各有优劣
二、一个单向链表的基本功能
一)、增加数据
第一种:直接将数据加在链表尾部
思路:
①遍历链表普通遍历(使用while)
1、将head赋值给可动指针temp
2、先判断是否达到尾结点,即temp.next==null
3、若达到尾结点则break;否则,移动当前结点temp,即temp=temp.next
4、当退出循环时,temp的位置为尾结点
②向结点添加数据
不考虑编号排序(add) 1、先找到尾结点 2、将尾结点的next指向将要添加的新节点,即temp.next=newHeroNode
第二种:根据编号,先排序再添加数据
①遍历链表,找到插入数据的位置
考虑编号排序时的遍历 1、会有三种情况 ①要添加的编号本来就应该在尾结点 ②要添加的编号本来就已经存在,不添加 ③要添加的编号在两个数据之间 2、介于第二种情况,需要新声明一个布尔变量flag,用来判断编号是否存在 3、判断适合插入的位置的条件:if(temp.next.no > newHeroNode.no)。
②向结点添加数据
考虑编号排序(addByOrder) 1、先遍历,找到需要插入的编号的前一个结点,作为此时的temp 2、将当前结点的下一个结点指向前一个结点的下一个结点,即newHeroNode.next=temp.next 3、将前一个结点的下一个结点指向当前结点,即temp.next=newHeroNode
思路图解:参考《我的第一本算法书》
二)、删除数据
1、思路
①遍历(需要判断链表是否为空),根据结点编号no,找到待删除结点的前一个结点
② 用一个布尔变量flag来标记是否找到该数据
③若找到,修改结点的指针域,temp.next = temp.next.next;
2、图解
三)、查找数据
就是简单的遍历加打印数据,但要注意此时的temp不是等于head,而是head.next
四)、修改数据
1、思路
①遍历,通过newHeroNode.no来找到原结点HeroNode.no的位置(这里的temp=head.next , 并且也需要一个flag来标记是否需要修改)
②根据no来修改其他数值
- temp.name = newHeroNode.name;
- temp.nickname = newHeroNode.nickname;
三、创建一个链表
1、定义HeroNode,每一个对象都是一个结点
内容:①数据域:编号no,名字name,昵称nickname
②指针域:HeroNode next;
2、创建一个对象,用来处理链表(增删查改)
①初始化头结点
②按照前面的功能思路,写各种方法,用于处理链表
四、代码实现
1、定义HeroNode
class HeroNode {
public int no;
public String name;
public String nickname;
public HeroNode next;
public HeroNode getNext() {
return 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 + '\'' +
'}';
}
}
2、实现各种功能
①增加数据
- 在链表尾部添加数据
public void add(HeroNode heroNode) {
HeroNode temp = head;
while (true) {
if (null == temp.next) {//达到尾结点
break;
}
temp = temp.next;
}
temp.next = heroNode;
}
-
按顺序添加数据
public void addByOrder(HeroNode heroNode) { HeroNode temp = head; boolean flag = false; while (true) { if (null == temp.next) { break; } if (heroNode.no < temp.next.no) { break; } else if (heroNode.no == temp.next.no) { flag = true; break; } temp = temp.next; } if (flag) { System.out.println("该编码已经存在,不可添加"); } else { heroNode.next = temp.next; temp.next = heroNode; } }
②删除数据
-
public void del(int no) { HeroNode temp = head; boolean flag = false; if (isEmpty()) { return; } 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.printf("待删除的结点%d不存在", no); } }
③查找数据
public void showlist() { if (isEmpty()) { return; } HeroNode temp = head.next; while (true) { //判断是否到链表最后 if (temp == null) { break; } System.out.println(temp); temp = temp.next; } }
④修改数据
public void update(HeroNode newHeroNode) { //判断是否为空 if (isEmpty()) { return; } HeroNode temp = head; boolean flag = false; while (true) { if (temp.next == null) { break; } if (temp.no == newHeroNode.no) { flag = true; break; } temp = temp.next; } if (flag) { temp.name = newHeroNode.name; temp.nickname = newHeroNode.nickname; } else { System.out.println("没有找到" + newHeroNode.no + "号的数据"); } }
⑤主方法测试
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 list = new SingleLinkedList(); list.add(hero1); list.add(hero2); list.add(hero3); list.add(hero4); list.showlist(); System.out.println("==========="); list.del(1); list.del(3); list.del(4); list.showlist(); System.out.println("============"); list.addByOrder(hero4); list.addByOrder(hero1); list.showlist(); System.out.println("============"); HeroNode newHeroHode = new HeroNode(3, "林冲匆", "豹子"); list.update(newHeroHode); list.showlist(); } }
⑥完整代码
package link; 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 list = new SingleLinkedList(); list.add(hero1); list.add(hero2); list.add(hero3); list.add(hero4); list.showlist(); System.out.println("==========="); list.del(1); list.del(3); list.del(4); list.showlist(); System.out.println("============"); list.addByOrder(hero4); list.addByOrder(hero1); list.showlist(); System.out.println("============"); HeroNode newHeroHode = new HeroNode(3, "林冲匆", "豹子"); list.update(newHeroHode); list.showlist(); } } class SingleLinkedList { //初始化一个头结点 private HeroNode head = new HeroNode(0, " ", " "); public void add(HeroNode heroNode) { HeroNode temp = head; while (true) { if (null == temp.next) {//达到尾结点 break; } temp = temp.next; } temp.next = heroNode; } public void addByOrder(HeroNode heroNode) { HeroNode temp = head; boolean flag = false; while (true) { if (null == temp.next) { break; } if (heroNode.no < temp.next.no) { break; } else if (heroNode.no == temp.next.no) { flag = true; break; } temp = temp.next; } if (flag) { System.out.println("该编码已经存在,不可添加"); } else { heroNode.next = temp.next; temp.next = heroNode; } } //根据no的编号来修改除了no以外的其他的结点信息 public void update(HeroNode newHeroNode) { //判断是否为空 if (isEmpty()) { return; } HeroNode temp = head; boolean flag = false; while (true) { if (temp.next == null) { break; } if (temp.no == newHeroNode.no) { flag = true; break; } temp = temp.next; } if (flag) { temp.name = newHeroNode.name; temp.nickname = newHeroNode.nickname; } else { System.out.println("没有找到" + newHeroNode.no + "号的数据"); } } public void del(int no) { HeroNode temp = head; boolean flag = false; if (isEmpty()) { return; } 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.printf("待删除的结点%d不存在", no); } } public void showlist() { if (isEmpty()) { return; } HeroNode temp = head.next; while (true) { //判断是否到链表最后 if (temp == null) { break; } System.out.println(temp); temp = temp.next; } } public boolean isEmpty() { if (null == head.next) { System.out.println("链表为空"); return true; } else { return false; } } } class HeroNode { public int no; public String name; public String nickname; public HeroNode next; public HeroNode getNext() { return 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 + '\'' + '}'; } }
五、运行结果