数据结构之单链表(java版)
单链表的介绍
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针(next域)链接次序实现的。链表在内存的存储如下图
链表是由一系列节点组成,这些节点不必在内存中相连。每一个节点均含有表元素和到包含该元素后继元素的节点链。称之为next链。下图为带头节点的单链表逻辑结构示意图
单链表优缺点
相对于顺序列表:
顺序表的元素是连续存储的,因此要在特定位置插入、删除元素需要把它之后的元素全部后移或前移一个元素的位置,时间开销很大;而单链表在插入或删除元素时,只需要改变它的next节点及插入或删除节点的指向即可。单链表在插入随机位置插入、删除元素的时间比顺序表少的多。
因为顺序表可以用下标来访问它的元素,所以它的元素是支持随机访问的;相比之下,单链表的数据是链式存储的,它的元素是不支持随机访问的,想要知道某个元素,只能从头结点开始遍历整个链表,知道找到了该元素为止。
单链表的实现
下面是使用带头节点的单链表实现,学生的增、删、改、查操作
添加学生代码实现
public void addStudent(Student student){
//因为头节点不能更改,故新建一个临时变量
Student temp = head;
//遍历学生链表
while (true){
//找到链表的最后
if (temp.next==null){
break;
}
//让节点指向下一个结点
temp = temp.next;
}
//找到最后一个(next为空的)节点存放student的地址
temp.next = student;
}
查询学生代码实现
public void selectStudent(int Id){
//因为头节点不能更改,故新建一个临时变量
Student temp = head;
//添加一个标志,找到了ID为true,未找到为false
boolean flag = false;
//遍历学生链表
while (true){
//找到链表的最后
if (temp.next==null){
break;
}
//找到位置退出循环
if (temp.next.Id == Id){
flag = true;
break;
}
}
if (flag){
System.out.println("找到了"+temp);
}else {
System.out.println("改节点不存在");
}
}
修改学生代码实现
public void updateStudent(Student student){
//因为头节点不能更改,故新建一个临时变量
Student temp = head;
//添加一个标志,找到了ID为true,未找到为false
boolean flag = false;
//遍历学生链表
while (true){
//找到链表的最后
if (temp.next==null){
break;
}
//找到位置退出循环
if (temp.next.Id == student.Id){
flag = true;
break;
}
temp = temp.next;
}
if (flag){
temp.next.name =student.name;
temp.next.score = student.score;
System.out.println("修改成功");
}else {
System.out.println("改节点不存在");
}
}
删除学生代码实现
public void deleteStudent(int Id){
//因为头节点不能更改,故新建一个临时变量
Student temp = head;
//添加一个标志,找到了ID为true,未找到为false
boolean flag = false;
//遍历学生链表
while (true){
//找到链表的最后
if (temp.next==null){
break;
}
//找到位置退出循环
if (temp.next.Id == Id){
flag = true;
break;
}
//让节点指向下一个结点
temp = temp.next;
}
if (flag){
temp.next = temp.next.next;
}else {
System.out.println("改节点不存在");
}
}
所有实现代码
public class Singlinkedlist{
private Student head = new Student(0,"",0);//创建头节点、
public void addStudent(Student student){
//因为头节点不能更改,故新建一个临时变量
Student temp = head;
//遍历学生链表
while (true){
//找到链表的最后
if (temp.next==null){
break;
}
//让节点指向下一个结点
temp = temp.next;
}
//找到最后一个(next为空的)节点存放student的地址
temp.next = student;
}
public void selectStudent(int Id){
//因为头节点不能更改,故新建一个临时变量
Student temp = head;
//添加一个标志,找到了ID为true,未找到为false
boolean flag = false;
//遍历学生链表
while (true){
//找到链表的最后
if (temp.next==null){
break;
}
//找到位置退出循环
if (temp.next.Id == Id){
flag = true;
break;
}
//让节点指向下一个结点
temp = temp.next;
}
if (flag){
System.out.println("找到了"+temp.next);
}else {
System.out.println("改节点不存在");
}
}
public void updateStudent(Student student){
//因为头节点不能更改,故新建一个临时变量
Student temp = head;
//添加一个标志,找到了ID为true,未找到为false
boolean flag = false;
//遍历学生链表
while (true){
//找到链表的最后
if (temp.next==null){
break;
}
//找到位置退出循环
if (temp.next.Id == student.Id){
flag = true;
break;
}
temp = temp.next;
}
if (flag){
temp.next.name =student.name;
temp.next.score = student.score;
System.out.println("修改成功");
}else {
System.out.println("改节点不存在");
}
}
public void deleteStudent(int Id){
//因为头节点不能更改,故新建一个临时变量
Student temp = head;
//添加一个标志,找到了ID为true,未找到为false
boolean flag = false;
//遍历学生链表
while (true){
//找到链表的最后
if (temp.next==null){
break;
}
//找到位置退出循环
if (temp.next.Id == Id){
flag = true;
break;
}
//让节点指向下一个结点
temp = temp.next;
}
if (flag){
temp.next = temp.next.next;
}else {
System.out.println("改节点不存在");
}
}
public void list(){
//因为头节点不能更改,故新建一个临时变量
Student temp = head;
while (true){
if (temp.next==null){
break;
}
temp=temp.next;
System.out.println(temp);
}
}
}
class Student{
public int Id;//学生学号
public String name;//学生姓名
public int score;//成绩
public Student next;//next域指向下一节点
public Student(int id, String name, int score) {
Id = id;
this.name = name;
this.score = score;
}
//从写toSting方便查看数据(不能将next域输出,不然会出现嵌套)
@Override
public String toString() {
return "Student{" +
"Id=" + Id +
", name='" + name + '\'' +
", score=" + score +
'}';
}
}
class AtTest{
public static void main(String[] args) {
Student s1 = new Student(1001, "张三", 90);
Student s2 = new Student(1002, "李四", 80);
Student s3 = new Student(1003, "王五", 88);
Student s4 = new Student(1004, "赵六", 78);
Singlinkedlist list = new Singlinkedlist();
//添加数据
list.addStudent(s1);
list.addStudent(s2);
list.addStudent(s3);
list.addStudent(s4);
//显示链表中所有数据
list.list();
//删除学生1001
System.out.println("删除1001");
list.deleteStudent(1001);
list.list();
System.out.println("修改赵六为小六,分数改为99");
list.updateStudent(new Student(1004, "小六", 99));
list.list();
System.out.println("查询");
list.selectStudent(1003);
}
}
运行结果