单链表
数据类
class Student{
int id;
String name;
Student next; // 指向下一个节点
public Student(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Student[ 学号 = " + id + ", 姓名 = " + name + ']';
}
}
单链表类
class SinglyLinkedList{
private Student head = new Student(0,""); //头节点
public Student getHead(){
return head;
}
//遍历
public void info(){
if (head.next == null){
System.out.println("链表为空");
return;
}
Student temp = head.next;
while (true){
if(temp == null){
break;
}
System.out.println(temp);
temp = temp.next;
}
}
//添加
public void add(Student student){
Student temp = head; //辅助变量
boolean isFalse = false;//添加的编号(id)是否存在
while (true){
if (temp.next == null){ //链表最后
break;
}
if (temp.next.id > student.id){ //编号比较,位置找到
break;
}
if (temp.next.id == student.id){//要新添加的id值已经存在
isFalse = true;//表示编号存在
break;
}
//temp 后移
temp = temp.next;
}
//判断id值是否存在
if (isFalse){
System.out.println("准备添加的数据已存在,学号为 = " + student.id);
}else
student.next = temp.next;
temp.next = student;
}
}
1、求单链表中有效节点的个数
通过头结点遍历
代码:
class Unity{
public static int getLenght(Student head){
int lenght = 0; //计数
if (head.next == null){//空链表
return lenght;
}
Student temp = head.next;
while (temp != null){
lenght++; //累加
temp = temp.next; //后移
}
return lenght;
}
}
测试:
public class Demo1 {
public static void main(String[] args) {
SinglyLinkedList list = new SinglyLinkedList();
Student st1 = new Student(11,"依依");
Student st2 = new Student(62,"尔尔");
Student st3 = new Student(393,"三三");
Student st4 = new Student(991,"斯斯");
list.add(st1);
list.add(st2);
list.add(st4);
list.add(st3);
list.info();
//1、求单链表中有效节点的个数
int lenght = Unity.getLenght(list.getHead());
System.out.println("单链表节点个数:" + lenght);
}
}
2、查找单链表中的倒数第k个结点0
链表长度 - 倒数结点(k) = 查找的节点位置
代码:
public static Student reciprocal(Student head,int index){
if (head.next == null){
System.out.println("链表为空,不存在节点");
return null;
}
int lenght = getLenght(head);//长度
if (index > lenght || index <= 0){
System.out.println("怎么说呢,不在这个范围内");
return null;
}
Student temp = head;
for (int i = 0; i <= lenght - index; i++) {
temp = temp.next;
}
return temp;
}
测试:
//2、查找单链表中的倒数第k个结点
Student reciprocal = Unity.reciprocal(list.getHead(), -1);
System.out.println(reciprocal);
3、单链表的反转
思路:
定义一个新的头节点,遍历原来的链表,取出每个节点,
放在新头节点的后面,更改链表的头节点指向。
1、创建新的头结点 newHead
两个辅助指针
temp = head.next; next = temp.next
2、遍历
newHead.next = temp; temp = next; next = temp.next
3、取出的节点放在最前面
temp.next = newHead.next;
4、更改指向
head.next = newHead.next;
代码:
public static void reversetList(Student head){
if (head.next == null || head.next.next == null){
//为空或只有一个节点时不需要反转
return;
}
//创建一个新的头节点
Student newHead = new Student(0,"");
Student temp = head.next;
Student next = null;
while (temp != null){
next = temp.next;//保存下一次要是有的节点
temp.next = newHead.next;//下一个节点指向新链表的最前端
newHead.next = temp;//连接到新链表上
temp = next;//temp 后移
}
head.next = newHead.next;//更改指向
}
测试:
System.out.println("**********反转**********");
Unity.reversetList(list.getHead());
list.info();
4、从尾到头打印单链表
思路:
方式一:进行反转,然后遍历打印
方式二:将数据存入数组,然后从尾打印
方式三:栈结构,先进后出(待补充。。。)
代码:数组
public static void printArray(Student head){
if (head.next == null || head.next.next == null){
//为空 或只有一个节点时 不需要
return;
}
int size = getLenght(head);
Student student[] = new Student[size];
Student temp = head.next;
for (int i = 0; i < size; i++) {
student[i] = temp;
temp = temp.next;
}
for (int i = 1; i <= size; i++) {
System.out.println(student[size - i]);
}
}
测试:
System.out.println("**********倒叙**********");
Unity.printArray(list.getHead());
5、合并两个有序的单链表,合并之后的链表依然有序
代码:感觉并不是很好,有没有其他办法?
public static void twoList(Student oneHead,Student twoHead){
if (oneHead.next == null || twoHead.next == null){
return;
}
Student one = oneHead.next;
Student two = twoHead.next;
Student student = new Student(0,"");
Student temp = student;
while (one != null){
while (two != null){
if (one.id > two.id){
temp.next = two;
temp = temp.next;
}else {
temp.next = one;
temp = temp.next;
break;
}
two = two.next;
}
//one 最后的id值比所有值都大
if (two == null && one != null){
temp.next = one;
temp = temp.next;
}
one = one.next;
}
//two最后的id值比所有值都大
while (true){
if (two != null){
temp.next = two;
temp = temp.next;
}else {
break;
}
two = two.next;
}
oneHead.next = student.next;
}
测试:
SinglyLinkedList list2 = new SinglyLinkedList();
Student stu1 = new Student(17,"11");
Student stu2 = new Student(12,"22");
Student stu3 = new Student(110,"33");
list2.add(stu1);
list2.add(stu2);
list2.add(stu3);
list2.info();
System.out.println("**********合并**********");
Unity.twoList(list.getHead(),list2.getHead());
list.info();