当前位置: 首页 > news >正文

单向链表在实际项目中的应用

前言

在实际项目中,单向链表经常被用来解决排队问题,因为链表允许动态地添加和移除元素,非常适合模拟队列(FIFO,先进先出)的行为。
这里的链表包含头节点,头结点的数据用来记录链表长度,该链表支持任意任意位置插入(插队)、尾插(按序排队),依据数据删除(找不到数据则返回错误),依据位置删除(超过链表节点数则返回失败)。

参考数据结构——单向链表-CSDN博客

有纰漏请指出,转载请说明。

学习交流请发邮件 1280253714@qq.com

单向链表在排队应用中的解决方案

单向链表在实际项目中的应用非常广泛,特别是在处理排队问题时,其灵活性和高效性使其成为理想的数据结构之一。以下是一些单向链表在实际项目中应用于排队问题的例子:

1. 订单处理系统

在电商或餐饮等行业中,订单处理系统需要高效地管理大量的订单请求。使用单向链表,可以将新到达的订单添加到链表的尾部,表示订单队列的末尾。处理订单时,可以从链表的头部开始,依次处理每个订单,直到队列为空。这种方式能够确保订单按照到达的顺序被处理,同时支持快速的插入和删除操作。

2. 任务调度系统

在操作系统或分布式系统中,任务调度系统负责管理和分配计算资源给各个任务。使用单向链表,可以将待调度的任务按照优先级或到达时间排序,形成一个任务队列。调度器可以从链表的头部开始,依次选择任务进行调度。当任务完成后,可以从链表中删除该任务节点。这种方式能够确保任务按照预定的顺序被调度,同时支持动态的插入和删除操作。

3. 网络连接管理

在网络通信中,服务器需要管理大量的客户端连接。使用单向链表,可以将每个客户端连接作为一个节点添加到链表中,形成一个连接队列。服务器可以遍历链表,对每个连接进行处理,如发送数据、接收数据或关闭连接等。当有新连接到达时,可以将其添加到链表的尾部;当连接关闭时,可以从链表中删除该节点。这种方式能够高效地管理网络连接,支持快速的插入和删除操作。

4. 事件驱动系统

在事件驱动的应用程序中,如游戏或实时监控系统,事件需要按照发生的时间顺序被处理。使用单向链表,可以将事件按照发生时间排序,形成一个事件队列。事件处理器可以遍历链表,依次处理每个事件。当有新事件到达时,可以将其插入到链表的合适位置,以保持事件的顺序性。这种方式能够确保事件按照正确的时间顺序被处理,同时支持动态的插入操作。

5. 打印机队列管理

在打印系统中,打印机需要管理多个打印任务。使用单向链表,可以将每个打印任务作为一个节点添加到链表中,形成一个打印任务队列。打印机可以遍历链表,依次处理每个打印任务。当有新的打印任务到达时,可以将其添加到链表的尾部;当任务完成后,可以从链表中删除该节点。这种方式能够高效地管理打印任务,确保任务按照到达的顺序被处理。

综上所述,单向链表在实际项目中的应用非常广泛,特别是在处理排队问题时。其灵活性和高效性使其成为管理动态数据集合的理想选择之一。

单向链表操作相关函数

typedef int data_t;typedef struct node {data_t data;struct node * next;
}listNode, * linkList;linkList list_create(void) //创建链表,即头节点
{linkList list;list = (linkList)malloc(sizeof(listNode));//给节点动态分配内存if (list == NULL)//判断是否申请内存成功 {return list;}	//如果成功了,则进行赋初值list->data = 0; //一般存放节点个数list->next = NULL;//刚开始时没有节点插入链表,所以该头节点即是尾节点return list; //返回头节点指针
}int list_tail_insert(linkList list, data_t data) //传入待插入的链表地址和待插入的数据
{linkList p = NULL;//定义临时指针变量linkList q = NULL;if (list == NULL) //检验传入的链表是否有效{return -1;}//创建新节点并检查有效性,存放待插入数据if ((p = (linkList)malloc(sizeof(listNode))) == NULL){return -1;}p->data = data;p->next = NULL;q = list;while (q->next != NULL) //遍历链表找尾部{q = q->next;}q->next = p;//插入链表,尾部的next指针指向新节点list->data++;//插入数据后,数据个数加一 return 0;
}// 插入函数,位置从0开始计数
int list_insert_at_position(linkList list, int position, data_t data) {linkList p = NULL; // 新节点指针linkList q = list; // 用于遍历的临时指针linkList prev = NULL; // 用于记录当前节点的前一个节点int i = 0; // 位置计数器// 检查位置是否有效(非负且不大于当前链表长度)if (position < 0) {return -1; // 位置无效}// 创建新节点并检查内存分配是否成功if ((p = (linkList)malloc(sizeof(listNode))) == NULL) {return -1; // 内存分配失败}p->data = data;p->next = NULL;if (list->next==NULL && position==0) {list->data = 1;list->next = p;} else{q = q->next; //跳过头节点// 遍历链表找到插入位置while (q != NULL && i < position) {prev = q;q = q->next;i++;}// 检查位置是否超出了链表长度if (i > position) {// 如果i大于position,说明position是在链表尾部或之后的位置,应该插入到尾部prev->next = p;} else {// 否则,插入到指定位置if (prev != NULL) {p->next = q;prev->next = p;} else {// 如果prev是NULL,说明position是0,应该插入到链表头部p->next = list;list = p;}}list->data++;//插入数据后,数据个数加一 }return 0; // 插入成功
}//寻找链表上某一位置的节点的地址,返回该节点地址
linkList list_get_addr(linkList list, int pos) //传入链表指针和待寻找节点的位置
{linkList p = NULL;int i = -1;if (list == NULL) {return NULL;}if (pos == -1) {return list;//如果是-1,则返回链表头节点,因为用0表示第一个节点的位置}p = list;while (i < pos) //遍历寻找{p = p->next;if (p == NULL) //没有到达指定位置,链表已经结尾了,位置错误,返回NULL{return NULL;}i++;		}return p;
}int list_deleteBaseOnPos(linkList list, int pos) 
{linkList p = NULL;linkList deleteNode = NULL;if (list == NULL) return -1;p = list_get_addr(list, pos-1);//寻找待删除节点的上一个节点if (p == NULL) {return -1;//没有找到则返回}if (p->next == NULL) //如果要删除的节点不存在,则返回{return -1;}deleteNode = p->next;//找到要删除的节点//将待删除的next指针赋给上一个节点的next指针p->next = deleteNode->next;//也可以用p->next = p->next->next;//释放删除节点的内存free(deleteNode);deleteNode = NULL;list->data--;//删除节点后,数据个数减一 return 0;
}int list_deleteBaseOnData(linkList list, data_t data) 
{int pos = 0;linkList p = NULL;linkList q = NULL;linkList deleteNode = NULL;if (list == NULL) return -1;q = list->next;while (q->data != data) //遍历链表找相同数据{q = q->next;pos++;if (pos >= list->data){return -1;//没有找到则返回}}p = list_get_addr(list, pos-1);//寻找待删除节点的上一个节点if (p == NULL) {return -1;//没有找到则返回}if (p->next == NULL) //如果要删除的节点不存在,则返回{return -1;}deleteNode = p->next;//找到要删除的节点//将待删除的next指针赋给上一个节点的next指针p->next = deleteNode->next;//也可以用p->next = p->next->next;//释放删除节点的内存free(deleteNode);deleteNode = NULL;list->data--;//删除节点后,数据个数减一 return 0;
}

实例 

int main(void)
{ linkList list;	list = list_create();//外部调用函数进行创建if (list == NULL)return -1;list_insert_at_position(list,0,7);list_tail_insert(list, 6);//在链表尾部进行插入list_tail_insert(list, 2);//在链表尾部进行插入list_tail_insert(list, 5);//在链表尾部进行插入list_tail_insert(list, 3);//在链表尾部进行插入list_tail_insert(list, 4);//在链表尾部进行插入list_insert_at_position(list,2,1);list_deleteBaseOnData(list, 2);list_deleteBaseOnPos(list, 3);while (1){}
}

仿真结果

变量定义

创建链表

list = list_create();

在第“0”个位置插入数据7

list_insert_at_position(list,0,7);

依次尾插数据6 2 5 3 4 

    list_tail_insert(list, 6);//在链表尾部进行插入
    list_tail_insert(list, 2);//在链表尾部进行插入
    list_tail_insert(list, 5);//在链表尾部进行插入
    list_tail_insert(list, 3);//在链表尾部进行插入
    list_tail_insert(list, 4);//在链表尾部进行插入

在第“2”个位置插入数据1

list_insert_at_position(list,2,1);

找到数据为2的节点并删除

list_deleteBaseOnData(list, 2);

http://www.lryc.cn/news/534909.html

相关文章:

  • 【系统架构设计师】操作系统 ③ ( 存储管理 | 页式存储弊端 - 段式存储引入 | 段式存储 | 段表 | 段表结构 | 逻辑地址 的 合法段地址判断 )
  • PDF另存为图片的一个方法
  • HTML之JavaScript运算符
  • 借助 ListWise 提升推荐系统精排效能:技术、案例与优化策略
  • C++中什么时候用. 什么时候用->
  • 从云原生到 AI 原生,谈谈我经历的网关发展历程和趋势
  • 【Python深入浅出】Python3正则表达式:开启高效字符串处理大门
  • Vue.js Vue CLI 安装与使用
  • 科技的尽头:在有限与永恒的夹缝中寻找文明的真谛
  • 【牛客】动态规划专题一:斐波那契数列
  • java8、9新特性
  • 作业:zuoye
  • redis底层数据结构——链表
  • 问题解决 4S 法
  • SQL-leetcode—1407. 排名靠前的旅行者
  • 机器学习(李宏毅)——Transformer
  • React进阶之React状态管理CRA
  • 攻克AWS认证机器学习工程师(AWS Certified Machine Learning Engineer) - 助理级别认证:我的成功路线图
  • 前端开发环境
  • Web自动化测试—测试用例流程设计
  • HTML全局属性与Meta元信息详解:优化网页的灵魂
  • day001 折半查找/二分查找
  • Linux 资源监控:优化与跟踪系统性能
  • java安全中的类加载
  • Node.js调用DeepSeek Api 实现本地智能聊天的简单应用
  • 分布式服务框架 如何设计一个更合理的协议
  • Unity使用iTextSharp导出PDF-02基础结构及设置中文字体
  • Kafka因文件句柄数过多导致挂掉的排查与解决
  • 【LeetCode Hot100 多维动态规划】最小路径和、最长回文子串、最长公共子序列、编辑距离
  • PRC框架-Dubbo