概述
- 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:data域+ next域构成,data就是存储数据的存储单元,next就是连接每个结点的地址数据。
单链表应用实例【模拟人员链表CRUD操作】
- 创建节点
package com.hf.structures.linkedlist;
public class EmpNode {
//排名
public int ranking;
//名字
public String name;
//下一个节点
public EmpNode next;
public EmpNode(int ranking, String name) {
this.ranking = ranking;
this.name = name;
}
@Override
public String toString() {
return "EmpNode{" +
"ranking=" + ranking +
", name='" + name + '\'' +
'}';
}
}
- 链表具体实现
① 初始化链表头
package com.hf.structures.linkedlist;
public class EmpLinkedList {
//初始化链表头
private EmpNode headNode = new EmpNode(0, "");
}
② 判断链表是否为null
/**
* 功能描述:
* 〈
* 判断链表是否为空
* 〉
*
* @className: EmpLinkedList
* @author: hf
* @version: 1.0.0
* @date: 2019/7/29 14:31
* @param: []
* @return: boolean
*
*/
private boolean isNull() {
return headNode.next == null;
}
③ 新增节点(EmpNode)到链表
/**
* 功能描述:
* 〈
* 添加人员信息到链表
* 1.找到链表的最后一个元素
* 2.temp.next=empNode;
* 〉
*
* @className: EmpLinkedList
* @author: hf
* @version: 1.0.0
* @date: 2019/7/17 14:07
* @param: [empNode 要添加的节点]
* @return: void
*/
public void add(EmpNode empNode) {
//1、找到当前链表的最后一个节点
EmpNode temp = headNode;
while (temp.next != null) {
//链表后移
temp = temp.next;
}
//2、将要添加的元素放到最后
temp.next = empNode;
}
/**
* 功能描述:
* 〈
* 按照人员成绩信息添加到链表
* 1. 首先找到新添加的节点的位置。
* 2. 新的节点.next = temp.next
* 3. 将temp.next = 新的节点
* 〉
*
* @className: EmpLinkedList
* @author: hf
* @version: 1.0.0
* @date: 2019/7/17 14:21
* @param: [empNode 要添加的节点信息]
* @return: void
*/
public void addByOrder(EmpNode empNode) {
EmpNode temp = headNode;
boolean flag = false;
while (true) {
//链表是否为空
if (temp.next == null) {
break;
}
//链表下一个人员的排名比当前要加入的人员排名大、标识位置找到
if (temp.next.ranking > empNode.ranking) {
break;
}
//若排名相同
if (temp.next.ranking == empNode.ranking) {
flag = true;
break;
}
//temp后移
temp = temp.next;
}
if (flag) {
System.out.println("链表元素已存在....");
} else {
//插入链表
empNode.next = temp.next;
temp.next = empNode;
}
}
④ 删除节点
/**
* 功能描述: <br>
* 〈
* 根据排名删除节点信息
* 1.找到要删除节点的前一个节点
* 2.temp.next=temp.next.next;
* 〉
*
* @className: EmpLinkedList
* @author: hf
* @version: 1.0.0
* @date: 2019/7/17 14:55
* @param: [raking]
* @return: void
*/
public void delete(int ranking) {
if (isNull()) {
return;
}
EmpNode temp = headNode;
boolean flag = false;
while (true) {
if (temp.next == null) {
break;
}
if (temp.next.ranking == ranking) {
flag = true;
break;
}
//链表元素后移
temp = temp.next;
}
if (flag) {
temp.next = temp.next.next;
} else {
System.out.println("没有要删除的节点....");
}
}
⑤ 修改节点信息
/**
* 功能描述: <br>
* 〈
* 修改链表元素
* 1.找到要修改的节点
* 2.重置节点数据
* 〉
*
* @className: EmpLinkedList
* @author: hf
* @version: 1.0.0
* @date: 2019/7/17 14:47
* @param: [empNode]
* @return: void
*/
public void update(EmpNode empNode) {
if (isNull()) {
System.out.println("当前链表为空....");
return;
}
//获取链表的第一个元素
EmpNode temp = headNode.next;
boolean flag = false;
while (true) {
//链表为空
if (temp == null) {
break;
}
//根据排名查找节点
if (temp.ranking == empNode.ranking) {
flag = true;
break;
}
//链表后移
temp = temp.next;
}
if (flag) {
temp.name = empNode.name;
} else {
System.out.println("链表中无此节点....");
}
}
⑥ 显示链表中所有节点
/**
* 功能描述: <br>
* 〈
* 遍历链表所有信息
* 〉
*
* @className: EmpLinkedList
* @author: hf
* @version: 1.0.0
* @date: 2019/7/17 14:12
* @param: []
* @return: void
*/
public void show() {
if (isNull()) {
System.out.println("当前链表为空....");
return;
}
//获取链表的第一个元素
EmpNode temp = headNode.next;
while (temp != null) {
//输出链表信息
System.out.println(temp);
//temp后移
temp = temp.next;
}
}
- 链表测试
package com.hf.structures.linkedlist;
public class TestEmpLinkedList {
public static void main(String[] args) {
//创建人员
EmpNode em1 = new EmpNode(1, "刘一");
EmpNode em2 = new EmpNode(2, "陈二");
EmpNode em3 = new EmpNode(3, "张三");
EmpNode em4 = new EmpNode(4, "李四");
EmpLinkedList empList = new EmpLinkedList();
//测试添加
empList.addByOrder(em1);
empList.addByOrder(em2);
empList.addByOrder(em3);
empList.addByOrder(em4);
//测试修改
EmpNode em5 = new EmpNode(4, "周七");
empList.update(em5);
//测试删除
empList.delete(1);
empList.delete(4);
empList.show();
}
}
单链表【编程题相关】
- 获取链表的有效节点个数
/**
* 功能描述:
* 〈
* 获取链表的有效节点个数
* 〉
*
* @className: EmpLinkedListUtils
* @author: hf
* @version: 1.0.0
* @date: 2019/7/18 9:40
* @param: [head 链表头节点]
* @return: int
*/
public static int getLength(EmpNode head) {
if (head.next == null) {
return 0;
}
int length = 0;
EmpNode temp = head.next;
while (temp != null) {
length++;
temp = temp.next;
}
return length;
}
- 查找单链表中的倒数第 n 个节点、若无此节点则返回null
/**
* 功能描述:
* 〈
* 查找单链表中的倒数第 n 个节点、若无此节点则返回null
* ① 接收head节点和index(表示是倒数第 n 个节点)
* ② 获取链表的总长度
* ③ 遍历链表、查找(size-index)个节点。
* 〉
*
* @className: EmpLinkedListUtils
* @author: hf
* @version: 1.0.0
* @date: 2019/7/18 9:46
* @param: [head 链表头, index]
* @return: com.hf.structures.linkedlist.EmpNode
*/
public static EmpNode findLastIndexNode(EmpNode head, int index) {
int size = getLength(head);
if (head.next == null || index <= 0 || index > size) {
return null;
}
EmpNode temp = head.next;
for (int i = 0; i < size - index; i++) {
temp = temp.next;
}
return temp;
}
- 单链表反转
/**
* 功能描述:
* 〈
* 单链表反转
* 〉
*
* @className: EmpLinkedListUtils
* @author: hf
* @version: 1.0.0
* @date: 2019/7/18 10:02
* @param: [head 链表头节点]
* @return: void
*/
public static void reverseList(EmpNode head) {
if (head.next == null || head.next.next == null) {
return;
}
//获取当前链表的第一个元素
EmpNode temp = head.next;
EmpNode next;
//创建一个新的辅助节点
EmpNode reverseHead = new EmpNode(0, "");
//遍历原来链表、每获取一个节点就将其取出放在链表reverseHead最前端
while (temp != null) {
//保存当前节点的下一个节点
next = temp.next;
//将temp的下一个节点指向新链表的最前端
temp.next = reverseHead.next;
//将temp链接到新的链表上
reverseHead.next = temp;
//temp后移
temp = next;
}
head.next = reverseHead.next;
}
- 反向输出链表节点信息
/**
* 功能描述:
* 〈
* 反向输出链表内容
* 〉
*
* @className: EmpLinkedListUtils
* @author: hf
* @version: 1.0.0
* @date: 2019/7/18 10:25
* @param: [head 链表头节点]
* @return: void
*/
public static void reversePrint(EmpNode head) {
if (head.next == null) {
return;
}
EmpNode temp = head.next;
Stack<EmpNode> stack = new Stack<>();
while (temp != null) {
stack.push(temp);
temp = temp.next;
}
while (stack.size() > 0) {
System.out.println(stack.pop());
}
}
- 合并两个有序的单链表、合并后依然有序
/**
* 功能描述:
* 〈
* 合并两个有序的单链表、合并后依然有序
* 〉
*
* @className: EmpLinkedListUtils
* @author: hf
* @version: 1.0.0
* @date: 2019/7/18 10:39
* @param: [h1 链表1, h2 链表2]
* @return: void
*
*/
public static EmpNode mergeLinkedList(EmpNode h1,EmpNode h2) {
if (h1.next == null && h2.next == null) {
return null;
}
if (h1.next == null) {
return h2;
}
if (h2.next == null) {
return h1;
}
//创建零时变量
EmpNode head;
EmpNode tm1 = h1.next;
EmpNode tm2 = h2.next;
//确认头结点
if (tm1.ranking <= tm2.ranking) {
head = tm1;
tm1 = tm1.next;
} else {
head = tm2;
tm2 = tm2.next;
}
EmpNode temp = head;
while (tm1 != null && tm2 != null) {
if (tm1.ranking <= tm2.ranking) {
temp.next = tm1;
tm1 = tm1.next;
}else {
temp.next = tm2;
tm2 = tm2.next;
}
temp = temp.next;
}
if (tm1 == null) {
temp.next = tm2;
}
if (tm2 == null) {
temp.next = tm1;
}
return head;
}