全网最详细Java 实现单链表(增、删、改、查、遍历等)
以学生管理系统为例:节点是学生,整个链表就是管理系统
节点定义、构造函数
学生类有学号、名字、下标等信息,默认所有的节点都是空的
为了方便。把所有的信息都设为public,这样就不用写get()和set()方法
public class Student {
public int number=0;
public int size=0; //下标
public String name;
public Student next =null;
public boolean isEmpty =true;
public Student(){
}
public Student(int number,String name, int size){
this.name =name;
this.number =number;
this.size =size;
this.isEmpty =false;
next=null;
}
public Student(int number,String name){
this.name =name;
this.number =number;
this.isEmpty =false;
next=null;
}
注意:为什么会使用 student.next来作比较?(注意这里有点绕)
1,如果student.next ==null, 那么说明它是链表的最后一个节点
2,关于删除操作
如果是双链表的话,使用student.before =studet.next 就可以删除student这个节点,但是因为单链表没有before这个属性,所以当遍历到student这个节点的时候,是找不到student前一个节点的,无法实现这个操作
但是我们可以通过新的方式实现,可以结合图片理解
原本的:student.before =student.next
新的: student…next= student.next.next
遍历链表(打印学生信息)
public void print(){
Student student =this;
while (true){
System.out.println("链表下标"+student.size+ " 学号:"+student.number+" 名字"+student.name);
if (student.next ==null){
break;
}//最后一个
student =student.next;
}
}
节点复制:调用方法的节点=新节点
public void copy(Student student){
this.number = student.number;
this.name =student.name;
this.next =student.next;
this.isEmpty =student.isEmpty;
}
增:添加学生信息(空节点添加信息、添加新节点)
如果student .next ==null 那么确定student是链表的最后一个节点,需要创建一个新节点来存储新数据
public void addStudent(Student s){
Student student =this;
while (true){
if (student.isEmpty ==true){
student.name =s.name;
student.number =s.number;
student.isEmpty =false;
break;
}//已经有一个新的节点了,直接添加信息就好
if (student.next ==null){
student.next =s;
s.size = student.size+1;
s.next =null;
/**
* 为什么要加这句话?难道next 不是null吗?这里有bug不知道怎么改
*/
break;
}//最后一个
student =student.next;
}
}
删:根据学号删除学生信息(这一段是链表操作最难的部分,如果你理解了,就搞定链表了)
public void remove(int removeNumber){
Student student =this;
while (true){
if (student.number ==removeNumber){
System.out.println("删除的学号"+student.number+"名字"+student.name);
Student newhead =student.next;
if (newhead !=null){
this.copy(newhead);
//头节点不是唯一的节点
}else{
System.out.println("这个链表被整个删除了");
Student student1 =new Student();
this.copy(student1);
}//头节点是唯一的节点,newhead是null
break;
}//要删除头节点
if (student.next ==null){
if (student.number!=removeNumber){
System.err.println("系统里没有这个学生");
}
break;
}//最后一个节点
if (student.next.number == removeNumber){
Student student3 =student.next.next;
System.out.println("删除的学号"+student.next.number+"名字"+student.next.name);
student.next =student3;
break;
}//不是删除头节点
student=student.next;
}
}
删:根据名字删除学生信息
public void remove(String name){
Student student =this;
int removeNumber =0;
while (true){
if (student.name.equals(name)){
removeNumber =student.number;
System.out.println("删除的学号"+student.number+"名字"+student.name);
break;
}
if (student.next ==null){
break;
}//最后一个
student=student.next;
}
Student student2 =this;
if (removeNumber ==0){
//没有找到
System.err.println("系统里没有这个学生");
}else{
//找到了
while (true){
if (student2.number ==removeNumber){
Student head =new Student();
head.next =student2.next;
// this= head;
break;
}//要头节点删除
if (student2.next ==null){
break;
}//最后一个节点
if (student2.next.number == removeNumber){
Student student3 =student2.next.next;
student2.next =student3;
break;
}//不是删除头节点
student2=student2.next;
}
}
}
改:根据学号修改名字
public void set(int newNumber, String newNme){
Student student =this;
while (true){
if (student.number ==newNumber){
student.name =newNme;
System.out.println("新的名字设置成功");
break;
}//对应的学生
if (student.next ==null){
if (student.number !=number){
System.err.println("没有对应的学号");
}//对应的学生
break;
}//最后一个
student =student.next;
}
}
查:根据学号查找名字
public String find(int number){
Student student =this;
while (true){
if (student.number ==number){
return student.name;
}//对应的学生
if (student.next ==null){
if (student.number !=number){
System.err.println("没有对应的学号");
}//对应的学生
break;
}//最后一个节点了
student =student.next;
}
return null;
}
根据学号,修改学生信息(以修改名字为例)
public void set(int newNumber, String newNme){
Student student =this;
while (true){
if (student.number ==newNumber){
student.name =newNme;
System.out.println("新的名字设置成功");
break;
}//对应的学生
if (student.next ==null){
if (student.number !=number){
System.err.println("没有对应的学号");
}//对应的学生
break;
}//最后一个
student =student.next;
}
}
测试代码部分
测试:添加、打印、根据学号修改名字
public void test_Set(){
Student student1 = new Student(1,"zjh1");
Student student8 = new Student(8,"zjh8");
Student student15 = new Student(15,"zjh15");
student1.addStudent(student8);
student1.addStudent(student15);
student1.print();
String name =student1.find(8);
System.out.println("名字"+name);
student1.set(8,"zjhNB");
String name2 =student1.find(8);
System.out.println("新名字"+name2);
student1.print();
}
测试:根据名字删除学生
public void test_Remove(){
Student student1 = new Student(1,"zjh1");
Student student2 = new Student(2,"zjh2");
Student student3 = new Student(3,"zjh3");
Student student8 = new Student(8,"zjh8");
Student student15 = new Student(15,"zjh15");
student1.addStudent(student2);
student1.addStudent(student3);
student1.addStudent(student8);
student1.addStudent(student15);
student1.print();
student1.remove("zjh8");
student1.remove("zjh15");
student1.remove("");
student1.print();
}
总结:链表本身不难,但是要注意遍历范围、特别是删除这个操作,线性表、哈希表都会用到,打好基础很重要。