生活中的链表
链表其实是一个一环扣一环的东西,最简单明了的就是我们的链子了,它就是一个一环扣一环的东西
链表介绍
- 链表在内存中的图解可以用下图来表示
- 链表是以节点的方式存储,是一个链式存储。
- 每个节点都有一个data域,和一个next域。
- 链表的内存空间可能是不连续的。
- 链表有带头节点和不带头节点两种,具体使用哪一种视情况而定。
单链表的代码书写
单链表的数据模型
单链表书写
这里我们使用一个学生作为节点类,来完成对链表的增加节点,删除节点,修改节点,遍历整个链表并打印输出。
public class Student {
private String name;
private int no;
private Student next;
public Student() {
}
public Student(String name,int no) {
this.name = name;
this.no = no;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName() {
this.name = name;
}
public Student getNext() {
return next;
}
public Student setNext() {
this.next = next;
}
}
/**
* 这是一个带头节点的链表模拟
*/
public class LinkListDemo {
public Student head = new Student(); // 设置头节点,没有实际数据存放
/**
* 将数据按照no顺序添加到链表中
* 实现思路:如果head的next域为空则直接插入到next域中
* 如果head节点的next域不为空,则遍历该节点,当节点的next域no大于要插入的
* 节点no,则将其插入在当前节点的next域
* 如果没有符合条件的,则插入在该链表的最后
* @param stu 学生节点
* @return 添加成功返回true, 失败返回false
*/
public boolean addLink(Student stu) {
if (head.getNext() == null) {
head.setNext(stu);
} else {
Student temp = head;
boolean flag= true;
while (true) {
if (temp.getNext() == null) {
break;
}else if (temp.getNext().getNo() == stu.getNo()) {
flag == false;
break;
} else if (temp.getNext().getNo() > stu.getNo()) {
break;
}
temp = temp.getNext();
}
if (flag) {
stu.setNext(temp.getNext());
tem.setNext(stu);
} else {
System.out.print("该no已经在这个链表中存在了");
}
return flag;
}
}
/**
* 删除链表中的节点
* 实现思路:如果head的next域为空,则直接返回false
* 如果head域不为空,则遍历该链表,找到则将该节点删除,否则返回false
* @param stu 需要删除的节点
* @return 删除成功返回true ,失败false
*/
public boolean delLink(Student stu) {
boolean flag = false;
if (head.getNext() == null) {
System.out.print("链表为空!!找不到元素");
return flag;
}
Student temp = head;
while (true) {
if (temp.getNext() == null) {
break;
} else if (temp.getNext().getNo == stu.getNo()) {
flag = true;
break;
}
temp = temp.getNext();
}
if (flag) {
temp.setNext(temp.getNext().getNext());
}
return flag;
}
/**
* 修改链表中的节点
* 实现思路:如果head的next域为空,则直接返回false
* 如果head域不为空,则遍历该链表,找到则将该节点修改,否则返回false
* @param stu 需要删除的节点
* @return 删除成功返回true ,失败false
*/
public boolean upLink(Student stu) {
boolean flag = false;
if (head.getNext() == null) {
System.out.print("链表为空!!找不到元素");
return flag;
}
Student temp = head;
while (true) {
if (temp.getNext() == null) {
break;
} else if (temp.getNo == stu.getNo()) {
flag = true;
break;
}
temp = temp.getNext();
}
if (flag) {
tem.setNo(stu.getNo());
tem.setName(stu.getName());
}
return flag;
}
}
面试题分享
- 计算单链表中有效元素个数
/**
* 实现思路:
* 遍历链表,计算其有效元素个数
* @param node需要计算的链表
* @return 计算得到的链表有效元素个数
*/
public static int getLength(Student head) {
if (null == head.getNext()) {
return 0;
}
Student temp = head.getNext();
int count = 0;
while (null != temp.getNext()) {
temp = temp.getNext();
count++;
}
return count;
}
- 查找单链表中倒数第K个节点
/**
* 实现思路:
* 1. 计算链表中有效元素个数length
* 2. 通过length - index 就是我们正方向数的下标位置
* 3. 遍历链表,找到指定下标的位置
* @param head 链表的头节点
* @param lastIndex需要查找的下标位置
* @return 找到则返回student对象,没有找到返回null
*/
public static Student findLastIndexNode(Student head, int lastIndex) {
if (head.getNext() == null) {
throw new NullPointsException();
}
int size = getLength(head);
int index = size - lastIndex;
Student temp = head.getNext();
int count = 0;
while (count < index) {
temp = temp.getNext();
count++;
}
}
- 单链表的反转
/**
* 实现思路:
* 1. 新创建一个临时链表的头节点
* 2. 遍历需要反转的链表
* 3. 将取下的节点插在临时链表头的next节点上
* 4. 将临时节点头的next拼接在head头节点next上
* 5. 完成链表反转
* @param head 需要反转的链表
*/
public static void reverseList(Student head) {
if (null == head.getNext()) {
throw new RuntimeException("链表为空!!!");
}
// 创建一个新的链表
Student tempHead = new Student();
Student temp = head.getNext();
// 记录下当前节点的下一个节点
Student next = null;
while (temp != null) {
next = temp.getNext();
temp.setNext(tempHead.getNext());
tempHead.setNext(temp);
temp = next;
}
head.setNext(tempHead.getNext());
}