Day24 目录遍历、双向链表、栈

day24 目录遍历、双向链表、栈


显示指定目录下的所有 .h 文件

功能描述

遍历指定目录(递归进入子目录),查找所有以 .h 为后缀的头文件,将其完整路径(路径 + 文件名)存储到双向链表中,并正向或反向打印输出。

核心技术点
  • 使用 opendir / readdir / closedir 进行目录遍历
  • 使用 DT_DIR 判断是否为目录,实现递归
  • 使用 sprintf 拼接路径字符串
  • 使用 strcmp 判断文件后缀是否为 .h
  • 使用双向链表动态存储匹配的文件路径

双向链表结构定义(DouLink.h
#ifndef _DOULINK_H_
#define _DOULINK_H_// 定义通用数据类型,用于存储文件路径
typedef struct person {char path[512];           // 存储文件的完整路径(含目录)
} DATATYPE;// 双向链表节点
typedef struct dou_node {DATATYPE data;            // 数据域struct dou_node *prev;    // 指向前一个节点struct dou_node *next;    // 指向后一个节点
} DouLinkNode;// 双向链表管理结构
typedef struct list {DouLinkNode *head;        // 指向链表头节点int clen;                 // 当前链表长度
} DouLinkList;// 遍历方向枚举
typedef enum {DIR_FORWARD,              // 正向遍历DIR_BACKWARD              // 反向遍历
} DIRECT;// 函数指针类型,用于查找、删除等操作
typedef int (*PFUN)(DATATYPE* data, void* arg);// 函数声明
DouLinkList *CreateDouLinkList();
int InsertHeadDouLinkList(DouLinkList *dl, DATATYPE *data);
int InsertTailDouLinkList(DouLinkList *dl, DATATYPE *data);
int InsertPosDouLinkList(DouLinkList *dl, DATATYPE *data, int pos);
DouLinkNode *FindDouLinkList(DouLinkList *dl, PFUN fun, void* arg);
int ModifyDouLinkList(DouLinkList *dl, char *name, DATATYPE *newdata);
int DeleteDouLinkList(DouLinkList *dl, char *name);
int GetSizeDouLinkList(DouLinkList *dl);
int IsEmptyDouLinkList(DouLinkList *dl);
int DestroyDouLinkList(DouLinkList *dl);
int ShowDouLinkList(DouLinkList *dl, DIRECT direct);#endif // _DOULINK_H_

说明:该头文件定义了通用的双向链表结构,适用于多种数据类型。当前用于存储 .h 文件路径。


双向链表实现(DouLink.c
#include "DouLink.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 创建空双向链表
DouLinkList *CreateDouLinkList() {DouLinkList *dl = malloc(sizeof(DouLinkList));if (NULL == dl) {perror("CreateDouLinkList malloc");return NULL;}dl->head = NULL;dl->clen = 0;return dl;
}// 头插法插入节点
int InsertHeadDouLinkList(DouLinkList *dl, DATATYPE *data) {DouLinkNode *newnode = malloc(sizeof(DouLinkNode));if (NULL == newnode) {perror("InsertHeadDouLinkList malloc");return 1;}memcpy(&newnode->data, data, sizeof(DATATYPE));newnode->next = NULL;newnode->prev = NULL;if (IsEmptyDouLinkList(dl)) {dl->head = newnode;} else {newnode->next = dl->head;dl->head->prev = newnode;dl->head = newnode;}dl->clen++;return 0;
}// 正向或反向打印链表
int ShowDouLinkList(DouLinkList *dl, DIRECT direct) {DouLinkNode *tmp = dl->head;if (DIR_FORWARD == direct) {while (tmp) {printf("%s\n", tmp->data.path);  // 输出文件路径tmp = tmp->next;}} else {// 找到最后一个节点while (tmp && tmp->next) {tmp = tmp->next;}// 从尾向前遍历while (tmp) {printf("%s\n", tmp->data.path);tmp = tmp->prev;}}return 0;
}// 判断链表是否为空
int IsEmptyDouLinkList(DouLinkList *dl) {return 0 == dl->clen;
}// 尾插法插入节点
int InsertTailDouLinkList(DouLinkList *dl, DATATYPE *data) {if (IsEmptyDouLinkList(dl)) {return InsertHeadDouLinkList(dl, data);} else {DouLinkNode *newnode = malloc(sizeof(DouLinkNode));if (NULL == newnode) {perror("InsertTailDouLinkList malloc");return 1;}memcpy(&newnode->data, data, sizeof(DATATYPE));newnode->next = NULL;newnode->prev = NULL;DouLinkNode *tmp = dl->head;while (tmp->next) {tmp = tmp->next;}newnode->prev = tmp;tmp->next = newnode;}dl->clen++;return 0;
}// 在指定位置插入节点
int InsertPosDouLinkList(DouLinkList *dl, DATATYPE *data, int pos) {int size = GetSizeDouLinkList(dl);if (pos < 0 || pos > size) {printf("InsertPosDouLinkList pos error\n");return 1;}if (0 == pos) {return InsertHeadDouLinkList(dl, data);} else if (size == pos) {return InsertTailDouLinkList(dl, data);} else {DouLinkNode *newnode = malloc(sizeof(DouLinkNode));if (NULL == newnode) {perror("InsertPosDouLinkList malloc");return 1;}memcpy(&newnode->data, data, sizeof(DATATYPE));newnode->next = NULL;newnode->prev = NULL;DouLinkNode *tmp = dl->head;while (pos--) {tmp = tmp->next;}newnode->next = tmp;newnode->prev = tmp->prev;tmp->prev = newnode;newnode->prev->next = newnode;dl->clen++;}return 0;
}// 通用查找函数:通过函数指针匹配数据
DouLinkNode *FindDouLinkList(DouLinkList *dl, PFUN fun, void* arg) {DouLinkNode* tmp = dl->head;while (tmp) {if (fun(&tmp->data, arg)) {return tmp;}tmp = tmp->next;}return NULL;
}// 获取链表长度
int GetSizeDouLinkList(DouLinkList *dl) {return dl->clen;
}// 销毁链表(释放所有节点和链表结构)
int DestroyDouLinkList(DouLinkList *dl) {DouLinkNode *tmp = NULL;while (dl->head) {tmp = dl->head;dl->head = dl->head->next;free(tmp);}free(dl);return 0;
}

理想运行结果

  • CreateDouLinkList() 返回一个空链表指针,head=NULL, clen=0
  • 插入操作后链表长度递增,ShowDouLinkList 可按正/反顺序输出路径
  • DestroyDouLinkList 释放所有内存,无泄漏

目录遍历与头文件查找(main.c
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DouLink.h"// 指定起始路径(可修改)
char path[] = "/home/linux/20250818cd";// 判断文件是否为 .h 后缀
int is_headfile(char* path) {if (strlen(path) < 3) return 0;char* tmp = &path[strlen(path) - 2];  // 取最后两个字符前的位置if (0 == strcmp(tmp, ".h")) {return 1;}return 0;
}// 递归遍历目录,将 .h 文件路径插入链表
int do_ls(char* path, DouLinkList* dl) {DIR* dir = opendir(path);if (NULL == dir) {perror("opendir");return 1;}struct dirent* info;while ((info = readdir(dir)) != NULL) {char newpath[512] = {0};sprintf(newpath, "%s/%s", path, info->d_name);  // 拼接完整路径if (info->d_type == DT_DIR) {// 忽略 . 和 ..if (strcmp(info->d_name, ".") == 0 || strcmp(info->d_name, "..") == 0) {continue;}// 递归进入子目录do_ls(newpath, dl);} else {// 非目录,检查是否为 .h 文件DATATYPE data = {0};if (is_headfile(newpath)) {strcpy(data.path, newpath);InsertHeadDouLinkList(dl, &data);  // 头插存储}}}closedir(dir);return 0;
}// 主函数:创建链表、遍历目录、打印结果
int main(int argc, char** argv) {DouLinkList* dl = CreateDouLinkList();do_ls("/home/linux", dl);  // 从 /home/linux 开始递归查找printf("=== 所有 .h 文件路径(正向输出)===\n");ShowDouLinkList(dl, DIR_FORWARD);DestroyDouLinkList(dl);return 0;
}

理想运行结果示例

=== 所有 .h 文件路径(正向输出)===
/home/linux/20250818cd/test.h
/home/linux/20250818cd/include/utils.h
/home/linux/20250818cd/module/config.h
  • 成功递归进入所有子目录
  • 正确识别 .h 文件并存储完整路径
  • 输出顺序取决于插入方式(头插 → 逆序)

双向链表(通用版)

功能说明

该双向链表支持插入、删除、查找、修改、遍历等操作,适用于存储结构化数据(如学生信息)。

数据结构定义(DouLink.h
#ifndef _DOULINK_H_
#define _DOULINK_H_typedef struct person {char name[32];char sex;int age;int score;
} DATATYPE;typedef struct dou_node {DATATYPE data;struct dou_node *prev;struct dou_node *next;
} DouLinkNode;typedef struct list {DouLinkNode *head;int clen;
} DouLinkList;typedef enum {DIR_FORWARD,DIR_BACKWARD
} DIRECT;typedef int (*PFUN)(DATATYPE* data, void* arg);// 函数声明(略去重复部分)
DouLinkList *CreateDouLinkList();
int InsertHeadDouLinkList(DouLinkList *dl, DATATYPE *data);
int InsertTailDouLinkList(DouLinkList *dl, DATATYPE *data);
int InsertPosDouLinkList(DouLinkList *dl, DATATYPE *data, int pos);
DouLinkNode *FindDouLinkList(DouLinkList *dl, PFUN fun, void* arg);
int ModifyDouLinkList(DouLinkList *dl, PFUN fun, void* arg, DATATYPE *newdata);
int DeleteDouLinkList(DouLinkList *dl, PFUN fun, void* arg);
int GetSizeDouLinkList(DouLinkList *dl);
int IsEmptyDouLinkList(DouLinkList *dl);
int DestroyDouLinkList(DouLinkList *dl);
int ShowDouLinkList(DouLinkList *dl, DIRECT direct);#endif

说明:此版本 DATATYPE 包含姓名、性别、年龄、成绩,适用于人员管理。


链表操作实现(DouLink.c
  • CreateDouLinkListInsertHead/InsertTail/InsertPosShowDouLinkListIsEmptyGetSize 实现同上(略)
  • 新增 ModifyDouLinkListDeleteDouLinkListDestroyDouLinkList
// 根据条件修改节点数据
int ModifyDouLinkList(DouLinkList *dl, PFUN fun, void *arg, DATATYPE *newdata) {DouLinkNode *tmp = FindDouLinkList(dl, fun, arg);if (NULL == tmp) {printf("ModifyDouLinkList failure...\n");return 1;}memcpy(&tmp->data, newdata, sizeof(DATATYPE));return 0;
}// 根据条件删除节点
int DeleteDouLinkList(DouLinkList *dl, PFUN fun, void *arg) {DouLinkNode *tmp = FindDouLinkList(dl, fun, arg);if (NULL == tmp) {printf("del failure...\n");return 1;}if (tmp == dl->head) {dl->head = dl->head->next;if (dl->head) dl->head->prev = NULL;} else {if (tmp->next) tmp->next->prev = tmp->prev;tmp->prev->next = tmp->next;}free(tmp);dl->clen--;return 0;
}// 销毁整个链表
int DestroyDouLinkList(DouLinkList *dl) {DouLinkNode *tmp;while (dl->head) {tmp = dl->head;dl->head = dl->head->next;free(tmp);}free(dl);return 0;
}

测试程序(test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DouLink.h"// 按姓名查找
int findperbyname(DATATYPE* data, void* arg) {return 0 == strcmp(data->name, (char*)arg);
}// 按年龄查找
int findperbyage(DATATYPE* data, void* arg) {return data->age == *(int*)arg;
}int main(int argc, char** argv) {DouLinkList* dl = CreateDouLinkList();DATATYPE data[] = {{"zhangsan", 'm', 20, 80},{"lisi", 'f', 23, 84},{"wangmaizi", 'f', 32, 90},{"guanerge", 'm', 50, 91},{"liubei", 'm', 51, 92},{"zhangfei", 'm', 50, 80},};InsertHeadDouLinkList(dl, &data[0]);InsertHeadDouLinkList(dl, &data[1]);InsertHeadDouLinkList(dl, &data[2]);printf("------------正向输出--------------------\n");ShowDouLinkList(dl, DIR_FORWARD);printf("------------反向输出--------------------\n");ShowDouLinkList(dl, DIR_BACKWARD);InsertTailDouLinkList(dl, &data[3]);printf("------------尾插后--------------------\n");ShowDouLinkList(dl, DIR_FORWARD);InsertPosDouLinkList(dl, &data[4], 2);printf("------------位置插入后--------------------\n");ShowDouLinkList(dl, DIR_FORWARD);int age = 50;DouLinkNode* tmp = FindDouLinkList(dl, findperbyage, &age);if (tmp) {printf("找到年龄为50的人: %s, 成绩: %d\n", tmp->data.name, tmp->data.score);}ModifyDouLinkList(dl, findperbyname, "lisi", &data[5]);printf("------------修改后--------------------\n");ShowDouLinkList(dl, DIR_BACKWARD);DeleteDouLinkList(dl, findperbyname, "liubei");printf("------------删除后--------------------\n");ShowDouLinkList(dl, DIR_BACKWARD);DestroyDouLinkList(dl);return 0;
}

理想运行结果

  • 正确插入、查找、修改、删除
  • 输出格式:name:xxx sex:x age:xx score:xx
  • 修改后 lisi 变为 zhangfeiliubei 被删除

顺序表与链表对比

对比项顺序表链表
存储方式连续内存空间物理上不连续,逻辑上连续
查找性能O(1) —— 支持随机访问O(n) —— 需遍历
插入/删除O(n) —— 需移动元素O(1) —— 只需修改指针(已知位置)
空间分配静态/固定大小,易浪费或溢出动态分配,灵活,无空间浪费

循环链表

  • 将单链表最后一个节点的 next 指针指向头节点第一个有效节点,形成环状结构。
  • 空表判断:head == NULL
  • 非空表遍历条件:p->next != head(代替 p->next != NULL
  • 常用于约瑟夫环、循环任务调度等场景。

双向链表(结构简写版)

typedef struct DulNode {ElemType data;               // 数据域struct DulNode *pri;         // 指向前驱struct DulNode *next;        // 指向后继
} DulNode, *DuLinkList;

✅ 注意:原始代码中 sturct 拼写错误,已修正为 struct


栈(Stack)

定义

限定仅在表尾进行插入和删除操作的线性表,遵循 “先进后出”(LIFO) 原则。

核心概念
  • 栈顶:允许操作的一端(插入/删除)
  • 栈底:不允许操作的一端
  • 基本操作
    • 入栈(Push)
    • 出栈(Pop)
    • 获取栈顶元素(GetTop)
分类
  • 顺序栈(数组实现)
  • 链式栈(链表实现)
    在这里插入图片描述
链式栈结构定义(LinkStack.h
#ifndef _LINKSTACK_H_
#define _LINKSTACK_H_typedef struct {char name[50];char sex;int age;int score;
} DATATYPE;typedef struct _linkstacknode {DATATYPE data;struct _linkstacknode *next;
} LinkStackNode;typedef struct {LinkStackNode* top;   // 栈顶指针int clen;             // 元素个数
} LinkStack;// 函数声明
LinkStack* CreateLinkStack();
int PushLinkStack(LinkStack* ls, DATATYPE* data);
int PopLinkStack(LinkStack* ls);
DATATYPE* GetTopLinkStack(LinkStack* ls);
int IsEmptyLinkStack(LinkStack* ls);
int GetSizeLinkStack(LinkStack* ls);
int DestroyLinkStack(LinkStack* ls);#endif

链式栈实现(LinkStack.c
#include "LinkStack.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>LinkStack* CreateLinkStack() {LinkStack* ls = malloc(sizeof(LinkStack));if (!ls) {perror("CreateLinkStack malloc error");return NULL;}ls->top = NULL;ls->clen = 0;return ls;
}int PushLinkStack(LinkStack* ls, DATATYPE* data) {LinkStackNode* newnode = malloc(sizeof(LinkStackNode));if (!newnode) {perror("PushLinkStack malloc error");return 1;}memcpy(&newnode->data, data, sizeof(DATATYPE));newnode->next = ls->top;ls->top = newnode;ls->clen++;return 0;
}int PopLinkStack(LinkStack* ls) {if (IsEmptyLinkStack(ls)) {printf("linkstack is empty\n");return 1;}LinkStackNode* tmp = ls->top;ls->top = ls->top->next;free(tmp);ls->clen--;return 0;
}DATATYPE* GetTopLinkStack(LinkStack* ls) {if (IsEmptyLinkStack(ls)) return NULL;return &ls->top->data;
}int IsEmptyLinkStack(LinkStack* ls) {return 0 == ls->clen;
}int GetSizeLinkStack(LinkStack* ls) {return ls->clen;
}int DestroyLinkStack(LinkStack* ls) {while (!IsEmptyLinkStack(ls)) {PopLinkStack(ls);}free(ls);return 0;
}

测试程序(test_stack.c
#include <stdio.h>
#include "LinkStack.h"int main() {LinkStack* ls = CreateLinkStack();DATATYPE data[] = {{"zhangsan", 'm', 20, 80},{"lisi", 'f', 23, 84},{"wangmaizi", 'f', 32, 90},{"guanerge", 'm', 50, 91},{"liubei", 'm', 51, 92}};for (int i = 0; i < 5; i++) {PushLinkStack(ls, &data[i]);}printf("出栈顺序(LIFO):\n");while (!IsEmptyLinkStack(ls)) {DATATYPE* tmp = GetTopLinkStack(ls);printf("name:%s score:%d\n", tmp->name, tmp->score);PopLinkStack(ls);}DestroyLinkStack(ls);return 0;
}

理想运行结果

出栈顺序(LIFO):
name:liubei score:92
name:guanerge score:91
name:wangmaizi score:90
name:lisi score:84
name:zhangsan score:80

使用栈实现 C 源文件符号匹配

原理
  • 遇到 ([{ 入栈
  • 遇到 )]} 检查栈顶是否匹配,匹配则出栈,否则报错
  • 文件结束时栈应为空,否则有未闭合符号
实现代码(check_brackets.c
#include <stdio.h>
#include <string.h>
#include "LinkStack.h"// 记录符号位置的结构
typedef struct {char c;int row;int col;
} SymData;int do_check(char* linebuf, LinkStack* ls, int num) {char* tmp = linebuf;SymData data = {0};SymData* top = NULL;int col = 1;while (*tmp) {switch (*tmp) {case '(':case '[':case '{':data.c = *tmp;data.row = num;data.col = col;PushLinkStack(ls, (DATATYPE*)&data);break;case ')':top = (SymData*)GetTopLinkStack(ls);if (!top || top->c != '(') {printf("括号不匹配: ) at row %d col %d\n", num, col);return 1;}PopLinkStack(ls);break;case ']':top = (SymData*)GetTopLinkStack(ls);if (!top || top->c != '[') {printf("括号不匹配: ] at row %d col %d\n", num, col);return 1;}PopLinkStack(ls);break;case '}':top = (SymData*)GetTopLinkStack(ls);if (!top || top->c != '{') {printf("括号不匹配: } at row %d col %d\n", num, col);return 1;}PopLinkStack(ls);break;}tmp++;col++;}return 0;
}int main() {LinkStack* ls = CreateLinkStack();FILE* fp = fopen("/home/linux/2.c", "r");if (!fp) {printf("fopen error\n");return 1;}int num = 1;char buf[1024];while (fgets(buf, sizeof(buf), fp)) {if (do_check(buf, ls, num)) {fclose(fp);DestroyLinkStack(ls);return 1;}num++;}if (IsEmptyLinkStack(ls)) {printf("✅ 所有括号匹配成功!\n");} else {SymData* top = (SymData*)GetTopLinkStack(ls);printf("❌ 存在未闭合符号: %c at row %d col %d\n", top->c, top->row, top->col);}fclose(fp);DestroyLinkStack(ls);return 0;
}

理想运行结果

  • 若括号全部匹配:输出 ✅ 所有括号匹配成功!
  • 若有不匹配:输出具体错误位置
  • 支持跨行匹配

栈的核心要点总结

  • 本质:受限制的线性表,仅允许在一端进行操作
  • 操作特性:先进后出(LIFO)
  • 两端定义
    • 栈顶:可进行插入/删除
    • 栈底:固定,不可操作
  • 主要作用
    • 递归调用管理
    • 表达式求值
    • 回溯算法
    • 符号匹配检查
  • 基本操作
    • 入栈(Push)
    • 出栈(Pop)
    • 获取栈顶(GetTop)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/93939.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/93939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JupyterLab 安装(python3.10)

目录 一、环境 二、安装 三、启动Jupyterlab 四、通过chrome浏览器进行访问 五、打开Jupyter Notebook 六、pandas验证 JupyterLab 是一个基于 Web 的交互式开发环境&#xff0c;是经典 Jupyter Notebook 的下一代版本。它支持多种编程语言&#xff08;如 Python、R、Juli…

【neo4j】安装使用教程

一、安装 1.0 前置条件 安装配置好jdk17及以上 注意我使用的是neo4j 5.26.10版本&#xff0c;匹配java17刚好 Java Archive Downloads - Java SE 17.0.12 and earlier 无脑安装即可 配置以下环境变量 1.1 安装程序 Neo4j Deployment Center - Graph Database & Anal…

AECS(国标ECALL GB 45672-2025)

车载紧急呼叫功能作为车辆遇险时的响应机制&#xff0c;为司机和乘客的安全营救提供通信支持。为了能够降低通信延迟&#xff0c;提高响应速度&#xff0c;基于4G/5G的下一代紧急呼叫技术&#xff08;NG eCall&#xff09;将在欧盟于2027年起成为强制标准&#xff0c;中国也已经…

week3-[循环嵌套]好数

week3-[循环嵌套]好数 题目描述 如果一个正整数 xxx 只有最左边一位不是 000&#xff0c;其余都是 000&#xff0c;那么称其为好数。例如 400040004000 和 222 都是好数&#xff0c;但是 120120120 不是。 给定正整数 nnn&#xff0c;在 111 到 nnn 间有多少个数是好数&#xf…

智能制造加速器:某新能源车智慧工厂无线网络优化提升方案

随着工业4.0和智能制造的快速发展&#xff0c;传统制造工厂的网络架构正面临前所未有的挑战。为了满足柔性生产、实时数据驱动以及高可靠运营的需求&#xff0c;某新能源车智慧工厂启动了一项无线网络优化提升项目。本项目通过部署智能组网设备&#xff0c;构建高效、稳定、智能…

nginx-自制证书实现

nginx-自制证书实现一、 确认nginx是支持https功能的二、生成私钥三、 根据ca.key生成nginx web服务器使用的证书签名请求文件nginx.csr四、使用ca.key给nginx.csr进行签名&#xff0c;生成公钥证书nginx.crt五、将证书与域名绑定六、添加域名解析并访问一、 确认nginx是支持ht…

FreeRTOS,事件标注组创建,xEventGroupCreate、xEventGroupCreateStatic

1. xEventGroupCreate ()&#xff1a;动态创建&#xff08;临时借内存&#xff09; 作用&#xff1a; 向系统&#xff08;FreeRTOS 的堆内存&#xff09;“临时申请” 一块内存来存放事件组&#xff0c;不需要我们自己提前准备内存。 例子&#xff08;基于你的代码修改&#xf…

Linux网络socket套接字(上)

目录 前言 1.Socket编程准备 1.理解源IP地址和目的IP地址 2.认识端口号 3.socket源来 4.传输层的典型代表 5.网络字节序 6.socket编程接口 2.Socket编程UDP 1.服务端创建套接字 2.服务端绑定 3.运行服务器 4.客户端访问服务器 5.测试 6.补充参考内容 总结 前言…

RK android14 Setting一级菜单IR遥控器无法聚焦问题解决方法

文章目录 前言 一、问题分析 1.1. 布局文件分析 1.2. Java代码 二、解决方法 2.1.移除冲突的滚动标志 2.2.解决有问题的初始化调用 2.3.完整补丁 前言 在Android系统Settings应用(packages/apps/Settings)的首页(SettingsHomepageActivity)中,存在一个 accessibility (无…

iOS 手势与控件事件冲突解决清单

总结一份「iOS 手势与控件事件冲突解决清单」&#xff0c;以后你遇到 UIButton / UITableView / UIScrollView 被手势拦截就能快速排查了&#xff1a;&#x1f4cc; iOS 手势与控件事件冲突常见解决办法1️⃣ cancelsTouchesInView&#x1f449; 最常用&#xff0c;决定手势识别…

笔试——Day45

文章目录第一题题目思路代码第二题题目思路代码第三题题目思路代码第一题 题目 kanan和高音 思路 双指针遍历数组&#xff0c;更新左右端点并计算最大值 代码 #include<iostream> #include<vector> using namespace std;int main() {int n; cin >> n;vect…

nnDetection网络结构分析

基于 RetinaNet 框架扩展&#xff0c;核心用于处理 3D 体积数据&#xff08;如医学影像 CT/MRI&#xff09;&#xff0c;通过 “Encoder-Decoder-Head” 架构实现多任务学习。以下从整体框架、核心模块细节、技术特点、应用场景四个维度展开分析。一、整体框架概览首先通过表格…

Torch -- 卷积学习day4 -- 完整项目流程

完整项目流程总结1. 环境准备与依赖导入import time import os import numpy as np import pandas as pd import torch import torch.nn as nn import torch.optim as optim import torchvision import torchvision.transforms as transforms from torch.utils.data import Dat…

MTK Linux DRM分析(七)- KMS drm_plane.c

一、简介在 Linux DRM&#xff08;Direct Rendering Manager&#xff09;子系统中&#xff0c;Plane&#xff08;平面&#xff09;代表了一个图像源&#xff0c;可以在扫描输出过程中与 CRTC 混合或叠加显示。每个 Plane 从 drm_framebuffer 中获取输入数据&#xff0c;并负责图…

OpenHarmony之 蓝牙子系统全栈剖析:从协议栈到芯片适配的端到端实践(大合集)

1. 系统架构概述 OpenHarmony蓝牙系统采用分层架构设计&#xff0c;基于HDF&#xff08;Hardware Driver Foundation&#xff09;驱动框架和系统能力管理&#xff08;System Ability&#xff09;机制实现。 1.1 架构层次 ┌─────────────────────────…

探索 Ultralytics YOLOv8标记图片

1、下载YOLOv8模型文件 下载地址&#xff1a;https://docs.ultralytics.com/zh/models/yolov8/#performance-metrics 2、编写python脚本 aaa.py import cv2 import numpy as np from ultralytics import YOLO import matplotlib.pyplot as pltdef plot_detection(image, box…

Matplotlib数据可视化实战:Matplotlib子图布局与管理入门

Matplotlib多子图布局实战 学习目标 通过本课程的学习&#xff0c;学员将掌握如何在Matplotlib中创建和管理多个子图&#xff0c;了解子图布局的基本原理和调整方法&#xff0c;能够有效地展示多个数据集&#xff0c;提升数据可视化的效果。 相关知识点 Matplotlib子图 学习内容…

【python实用小脚本-194】Python一键给PDF加水印:输入文字秒出防伪文件——再也不用开Photoshop

Python一键给PDF加水印&#xff1a;输入文字秒出防伪文件——再也不用开Photoshop PDF加水印, 本地脚本, 零会员费, 防伪标记, 瑞士军刀 故事开场&#xff1a;一把瑞士军刀救了投标的你 周五下午&#xff0c;你把 100 页标书 PDF 发给客户&#xff0c;却担心被同行盗用。 想加水…

开源 C++ QT Widget 开发(四)文件--二进制文件查看编辑

文章的目的为了记录使用C 进行QT Widget 开发学习的经历。临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 C QT Widget 开发&#xff08;一&#xff09;工程文件结构-CSDN博客 开源 C…

【密码学实战】X86、ARM、RISC-V 全量指令集与密码加速技术全景解析

前言 CPU 指令集是硬件与软件交互的核心桥梁&#xff0c;其设计直接决定计算系统的性能边界与应用场景。在数字化时代&#xff0c;信息安全依赖密码算法的高效实现&#xff0c;而指令集扩展则成为密码加速的 “隐形引擎”—— 从服务器端的高吞吐量加密&#xff0c;到移动端的…