顺序表在实际中的应用场景
-
购物清单:想象一下你去超市购物,你可以将需要购买的物品列成一张清单。这个清单就像是顺序表,物品的顺序就是它们在清单上的顺序。你可以通过清单上每个项目的位置快速找到需要的物品。
-
邮寄地址簿:在你的邮寄地址簿中,你可能按照字母顺序存储朋友和家人的地址。每个人的地址就像顺序表中的一个元素,你可以通过字母顺序快速找到他们的地址。
-
班级花名册:老师可能会用一本班级花名册来记录学生的信息,比如姓名、学号、出生日期等。这本花名册就像是一个顺序表,每个学生的信息就是顺序表中的一个元素,按照他们的出现顺序排列。
-
音乐播放列表:在你的手机或电脑上,你可能有一个音乐播放列表,里面按照你的喜好排列了一系列歌曲。这个播放列表就是一个顺序表,每首歌曲就是一个元素,按照它们在列表中的顺序播放。
-
图书馆书架:想象一下一排排整齐的书籍在图书馆的书架上。每本书就像顺序表中的一个元素,它们按照某种顺序排列,比如按照作者的姓氏首字母或者按照主题分类。
(顺序表)以学生信息为例的示例代码(类-方法-实现)
package data_structure.Sequential_List;
public class Student {
String name;
double score;
int ID;
public Student(String name, int ID, double score) {
this.name = name;
this.score = score;
this.ID = ID;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
@Override
public String toString() {
return "anme=" + name + ",ID=" + ID + ",score=" + score;
}
}
package data_structure.Sequential_List;
public class SequentialMethod {
//顺序表的最大存储容量为10个
Student[] students = new Student[10];
//记录现在的数量
int count = 0;
//添加元素时间复杂度O(1)
public void add(Student student) {
//count在允许的范围
if (count >= 0 && count < students.length) {
int i = count;
students[i] = student;
count++;
} else {
System.out.println("内存已满!");
}
}
//查询指定元素时间复杂度O(1)
public void search(int index) {
if (index >= 0 && index < count) {
System.out.println("name = " + students[index].name + ",ID = " + students[index].ID + ",score = " + students[index].score);
} else {
System.out.println("索引失败!");
}
}
//插入指定位置和指定元素时间复杂度O(n)
public void insert(Student student, int index) {
if (index >= 0 && index <= count && count < students.length - 1) {
for (int i = count; i >= index; i--) {
students[i + 1] = students[i];
}
students[index] = student;
count++;
} else {
System.out.println("索引错误或内存已满!");
}
}
//删除指定位置的元素时间复杂度O(n)
public void delete(int index) {
if (index >= 0 && index <= count) {
for (int i = index; i <= count; i++) {
students[i] = students[i + 1];
}
count--;
} else {
System.out.println("索引失败!");
}
}
//遍历所有的元素
public void listAll(){
for(int i=0;i<count;i++){
Student student = students[i];
System.out.println("name = " + student.name + ",ID = " + student.ID + ",score = " + student.score);
}
}
}
package data_structure.Sequential_List;
public class mainText {
public static void main(String[] args) {
SequentialMethod sm = new SequentialMethod();
sm.add(new Student("jia",101,23));
sm.add(new Student("dfs",104,343));
sm.add(new Student("asdf",102,23442));
System.out.println("----------------------添加元素成功----------------------------");
sm.listAll();
System.out.println("-------------------寻找索引为 1 的元素-------------------------");
sm.search(1);
System.out.println("-------------插入 1 位置和指定 aaaaaaaaaa,103,7898------------");
sm.insert(new Student("aaaaaaaaaa",103,7898),1);
sm.listAll();
System.out.println("--------------------删除指定 2 索引---------------------------");
sm.delete(2);
sm.listAll();
}
}
单链表在实际中的使用场景
-
联系人列表:在手机通讯录或电子邮件客户端中,联系人列表通常使用单链表来存储。每个联系人都可以表示为一个节点,节点中包含联系人的姓名、电话号码等信息,而指针则指向下一个联系人的节点。
-
任务列表:在任务管理应用程序中,任务列表可以使用单链表来组织。每个任务都是一个节点,包含任务的描述、截止日期等信息,而指针指向下一个任务节点。
-
浏览器历史记录:在网页浏览器中,浏览历史记录可以使用单链表来实现。每个访问的网页可以表示为一个节点,节点中包含网页的 URL、访问时间等信息,而指针则指向前一个访问的网页节点。
-
文本编辑器的撤销功能:在文本编辑器中,撤销功能可以使用单链表来实现。每次编辑操作会创建一个新的节点,包含编辑前后的文本内容,而指针指向上一个编辑状态的节点,以便进行撤销操作。
-
队列的实现:在计算机科学中,队列是一种常见的数据结构,用于存储按照先进先出(FIFO)顺序排列的元素。队列可以使用单链表来实现,其中链表的头部表示队列的前端,而尾部表示队列的后端。
-
循环播放列表:在音乐播放器或视频播放器中,循环播放列表可以使用单链表来实现。每个音乐或视频文件可以表示为一个节点,而指针指向下一个要播放的文件节点,最后一个节点指向列表的头部,实现循环播放。
(单链表)以学生信息为例的示例代码(类-方法-实现)
package data_structure.Single_Linked_List;
public class Stud_Node {
String name;
int ID;
double score;
Stud_Node next;
@Override
public String toString() {
return name+","+ID+","+score;
}
public Stud_Node(String name, int ID, double score) {
this.name = name;
this.ID = ID;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public Stud_Node getNext() {
return next;
}
public void setNext(Stud_Node next) {
this.next = next;
}
}
package data_structure.Single_Linked_List;
//时间复杂度都为O(n),初始化的时间复杂度为O(1)
public class SingleList_Method {
//表头
private Stud_Node head;
//记录计数器
private int count;
//初始化链表
public void initLinkedList() {
head = null;
count = 0;
}
//在链表尾部添加学生记录,尾插法
public void add(Stud_Node node) {
Stud_Node current;
if (head == null) {
head = node;
} else {
current = head;
//找到链表的尾部
while (current.getNext() != null) {
current = current.getNext();
}
current.setNext(node);
}
node.setNext(null);
count++;
}
//显示链表中所有学生信息
public void listAll() {
Stud_Node current = head;
while (current != null) {
System.out.println(current);
current = current.getNext();
}
System.out.println("一共有" + count + "条记录!");
}
//根据学生ID查询学生信息并输出
public void search(int ID) {
Stud_Node current = head;
//是否找到想要的数据,0未找到,1找到
int flag = 0;
while (current != null) {
if (current.getID() == ID) {
System.out.println(current);
flag = 1;
}
current = current.getNext();
}
if (flag != 1) {
System.out.println("未找到此学生信息!");
}
}
// 删除某个学生的信息,链表为空,删除的节点是头节点,删除的节点在链表中间
public void delete(int id) {
if (head == null) {
System.out.println("链表为空,删除失败!");
return;
}
// 如果要删除的是头节点
if (head.getID() == id) {
head = head.getNext();
count--;
return;
}
Stud_Node current = head;
Stud_Node prev = null;
while (current != null && current.getID() != id) {
prev = current;
current = current.getNext();
}
// 如果找到了要删除的节点
if (current != null) {
// 删除节点在链表中间
prev.setNext(current.getNext());
count--;
} else {
System.out.println("未找到要删除的节点");
}
}
//在指定的id元素后面插入新的元素
public void insert(Stud_Node student, int id) {
if (head == null) {
head = student;
System.out.println("链表为空,直接在头节点插入");
}
Stud_Node current = head;
while (current != null && current.getID() != id) {
current = current.getNext();
}
student.setNext(current.getNext());
current.setNext(student);
count++;
}
}
package data_structure.Single_Linked_List;
public class mainText {
public static void main(String[] args) {
SingleList_Method sm = new SingleList_Method();
sm.initLinkedList();
System.out.println("---------------------------");
//向链表中加入数据
sm.add(new Stud_Node("jjjj",101,89.3));
sm.add(new Stud_Node("hhhh",104,89.3));
sm.add(new Stud_Node("rrrr",102,89.3));
sm.listAll();
System.out.println("---------------------------");
//根据 ID=104 查询学生信息
sm.search(104);
System.out.println("---------------------------");
//删除 ID=102 学生信息
sm.delete(104);
sm.listAll();
System.out.println("---------------------------");
sm.insert(new Stud_Node("jiahongrui",105,893),101);
sm.listAll();
}
}
双向链表在实际中的使用场景
-
浏览器历史记录:与单链表相比,双向链表更适合表示浏览器历史记录。每个页面访问都可以作为一个节点存储,节点中包含页面的信息,如URL、标题等。通过双向链表,用户可以方便地回退到之前访问的页面,而不仅仅是后退。
-
双向队列(Deque):双向链表可以被用作双向队列的基础数据结构。双向队列支持在队列的两端进行元素的插入和删除操作,而双向链表正是能够有效支持这种操作的数据结构。
-
文本编辑器的撤销与重做功能:在文本编辑器中,除了撤销功能外,还有重做功能。双向链表可以被用来实现这两种功能。每次编辑操作都会创建一个节点,用户可以通过双向链表方便地在编辑操作之间进行切换。
-
LRU缓存算法:LRU(Least Recently Used)缓存算法中,双向链表常被用来实现LRU缓存。缓存中的每个数据项都是一个节点,当一个数据项被访问时,它被移动到链表的头部,而当缓存满时,链表尾部的数据项被移除。
-
文件系统中的索引结构:在文件系统中,双向链表可以被用来表示目录结构或者文件块的索引结构。每个目录或文件块可以是一个节点,节点之间通过双向指针相连,实现快速的文件查找和访问。
(双向链表)以学生信息为例的示例代码(类-方法-实现)
package data_structure.Double_Linked_list;
public class stu_Node {
String name;
int ID;
double score;
stu_Node next;
stu_Node pre;
@Override
public String toString() {
return name + "," + ID + "," + score;
}
public stu_Node(String name, int ID, double score) {
this.name = name;
this.ID = ID;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public stu_Node getNext() {
return next;
}
public void setNext(stu_Node next) {
this.next = next;
}
public stu_Node getPre() {
return pre;
}
public void setPre(stu_Node pre) {
this.pre = pre;
}
}
package data_structure.Double_Linked_list;
public class Linked_Method {
stu_Node head = null;
stu_Node tail = null;
private int count;
//初始化
public void initLinkedList() {
head = null;
tail = null;
count = 0;
}
//尾插法
public void add(stu_Node node){
stu_Node current;
//如果头节点为空
if(head==null){
head=node;
tail=node;
}else{
current=tail;
current.next=node;
node.pre=current;
tail=node;
}
count++;
}
//遍历所有元素
public void listAll(){
stu_Node current = head;
while(current!=null){
System.out.println(current);
current=current.getNext();
}
System.out.println("一共有"+count+"条记录!");
}
//根据id寻找学生信息并显示
public void search(int id){
stu_Node current = head;
int flag = 0;
while(current!=null){
if(current.getID()==id){
System.out.println(current);
flag=1;
break;
}
current=current.getNext();
}
if(flag!=1){
System.out.println("未找到学生信息!");
}
}
//在指定的id后面添加元素
public void insert(stu_Node student, int id) {
if (head == null) {
head = student;
System.out.println("链表为空,直接在头节点插入");
count++;
return;
}
stu_Node current = head;
// 遍历链表查找指定ID的节点
while (current != null && current.getID() != id) {
current = current.getNext();
}
// 如果找到了指定ID的节点
if (current != null) {
// 将新节点的下一个节点设置为当前节点的下一个节点
student.setNext(current.getNext());
// 将新节点的前一个节点设置为当前节点
student.setPre(current);
// 如果当前节点不是尾节点,则将当前节点的下一个节点的前一个节点设置为新节点
if (current.getNext() != null) {
current.getNext().setPre(student);
}
// 将当前节点的下一个节点设置为新节点
current.setNext(student);
count++;
} else {
System.out.println("未找到要插入的位置");
}
}
}
package data_structure.Double_Linked_list;
import data_structure.Single_Linked_List.Stud_Node;
public class mainText {
public static void main(String[] args) {
Linked_Method lm = new Linked_Method();
lm.initLinkedList();
System.out.println("---------------------------");
//向链表中加入数据
lm.add(new stu_Node("jjjj",101,89.3));
lm.add(new stu_Node("hhhh",104,89.3));
lm.add(new stu_Node("rrrr",102,89.3));
lm.listAll();
System.out.println("---------------------------");
lm.search(101);
System.out.println("---------------------------");
lm.insert(new stu_Node("werwerwe",105,82.4),104);
lm.listAll();
System.out.println("---------------------------");
}
}