【数据结构】单向链表实现 超详细

目录

一. 单链表的实现

1.准备工作及其注意事项

1.1 先创建三个文件

1.2 注意事项:帮助高效记忆和理解

2.链表的基本功能接口

2.0 创建一个 链表

2.1 链表的打印

 3.链表的创建新节点接口

4.链表的节点插入功能接口

4.1 尾插接口

4.2 头插接口  

  4.3 指定位置 pos 之前 插入接口

 4.4 指定位置pos 之后 插入接口(推荐)

5.链表表的删除功能接口

5.1 尾删接口

5.2头删接口

5.3 删除 指定位置 pos 节点 接口

5.4 删除  指定位置 pos ==之后== 的一个 节点 接口

6.链表的  查找  接口

7.链表的  销毁  接口

二、总代码

SList.h

SList.c

test.c


前言:(受篇幅限制,为了划清知识模块,进行分章节讲解)

若想了解清楚 链表的概念和分类 

可以点击跳转 这一章节----> :【数据结构】链表的概念 及 分类 (使用比喻解释概念)


一. 单链表的实现

1.准备工作及其注意事项
1.1 先创建三个文件

 解释这三个文件的作用
 1、头文件SList.h  是来声明接口函数,定义链表,将几个公共用到的库函数集合起来
 2、源文件SList.c  是用来具体实现接口
 3、源文件test.c  用于接口的测试工作 ,即具体的使用场景

1.2 注意事项:帮助高效记忆和理解

1. 但凡是删除,必须 断言 链表不能为 空,避免传过来的是NULL指针 assert(*pphead);
2. 传递二级指针,要断言 不能为 NULL ,指针不能为空:assert(pphead);
3. 指定位置 pos 时,要确保pos存在:assert(pos);
4. (pphead)->next;  解引用前一定要加 括号,* 号 优先级 < 箭头操作符
5. 链表的所有插入接口:链表为空: 没有节点 就直接插入
6.要找 前一个节点 prev 或 后一个节点 next 时, 一定要确保 其本身存在!!!!
7.当指定位置 pos 刚好是 头节点时 就没有 prev 了

2.链表的基本功能接口
2.0 创建一个 链表
// 创建链表节点结构体
// 和顺序表创建原理相同,可以看我的 【顺序表】章节
typedef  int  SLDataType;
typedef struct SListNode
{SLDataType data;struct SListNode* next;
}SLTNode;
2.1 链表的打印
// 打印函数
//注意这里的 phead 仅表示单向链表传递过来的 第一个节点地址,不是 双向链表的带头节点 
void SLTPrint(SLTNode* phead)
{SLTNode* ptemp = phead;while (ptemp) // ptemp != NULL 说明为是有效的节点,则循环打印{printf("%d -> ", ptemp->data);ptemp = ptemp->next; // 更新 ptemp :保存下个节点的地址:遍历节点的关键}printf("NULL\n");
}
 3.链表的创建新节点接口
// 创建新节点函数:所有的插入接口,都需要 创建新节点
SLTNode* STLCreatNode(SLDataType x)
{// 先创建 一个 新节点SLTNode* newNode = (SLTNode*)malloc(sizeof(SLTNode));newNode->data = x;newNode->next = NULL;return newNode;
}
4.链表的节点插入功能接口
4.1 尾插接口

链表的尾插法
几种情况
1、链表非空:先找到尾节点,然后直接将尾节点 的 next 指向 新节点,(形成链接), 新节点 则 指向 NULL 变成 新的尾节点
2、链表为空:将头指针phead更新 成 新插入节点的地址,然后新节点 next 指向 NULL

// 注意:plist 头指针是 时刻更新为了指向头节点,当创建新的头节点后,要更新 plist ,而若要真正改变 plist 的值,需要传地址
// 传递过来的 头指针 &plist 是 一级指针 plist 的地址,要用 二级指针 pphead 来接收 ; 而 *pphead == plist 
// void SLTPushBack(SLTNode* phead, SLDataType x) // 错误写法:传值void SLTPushBack(SLTNode** pphead, SLDataType x)
{assert(pphead); // 传递过来的 一级指针的地址 二级指针 不能为 NULL// 先创建 一个 新节点SLTNode* newNode = STLCreatNode(x);// 1、链表为空if (*pphead == NULL){*pphead = newNode;return;}// 2、链表非空SLTNode* ptail = *pphead; // 因为要找 尾节点:干脆命名为 tail//本质是:找到尾节点的地址,而不是 尾节点的 nextwhile (ptail->next) {ptail = ptail->next;}ptail->next = newNode;
}

4.2 头插接口  

void SLTPushFront(SLTNode** pphead, SLDataType x)
{assert(pphead); // 传递过来的 一级指针的地址 二级指针 不能为 NULL// 先创建 一个 新节点SLTNode* newNode = STLCreatNode(x);newNode->next = *pphead; // 先将原本的 头指针放在 新节点的next*pphead = newNode; // 更新 头指针
}

  4.3 指定位置 pos 之前 插入接口

// 在指定位置节点pos 之前插入数据 
// 思路:找三个节点 :prev     newNode      next 
//                  前      本身新节点     后         为了找到 地址 才能将三者链接起来
// 注意:要找 前一个节点 prev 时, 一定要确保 其本身存在!!! 
// 当 pos 刚好是 头节点时 就没有 prev 了,特殊情况, 否则会因为找不到prev而 程序奔溃
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLDataType x)
{assert(pphead); // 指针不能为空assert(pos); // pos 不能为空assert(*pphead); // 链表不能为空: pos 是链表中 的一个有效节点,pos 不为空,链表也不能为 空// 创建新节点SLTNode* newNode = STLCreatNode(x);if (*pphead == pos){// 当 pos 刚好是 头节点时 就用 头插法:调用之前写的函数接口SLTPushFront(pphead, x);return;}SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}// 三者关联起来:  prev -> newNode -> posnewNode->next = pos;prev->next = newNode;
}
 4.4 指定位置pos 之后 插入接口(推荐)

// 在指定位置节点pos 之后插入数据: 注意一下错误写法: 和正确写法刚好相反
// 特点:有了 pos 就不需要 头节点了!!
void SLTInsertAfter(SLTNode*pos, SLDataType x)
{assert(pos); // pos 不能为空// 创建新节点SLTNode* newNode = STLCreatNode(x);newNode->next = pos->next;pos->next = newNode;
}
5.链表表的删除功能接口
5.1 尾删接口

// 链表的尾删法
// 思路:删除尾节点 以及  前一个节点 pre 的next 要置为 NULL
// 要注意 只有一个节点时,没有前置节点 pre!!!!
void SLTPopBack(SLTNode** pphead)
{assert(pphead); // 一级指针为plist 指向头节点,传递过来的 一级指针的地址二级指针不能为 NULLassert(*pphead); // 一级指针为plist 指向头节点, *pphead == plist 这个指针也不能为 NULL 不能为空链表// 链表非空// 链表只有一个节点时if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;return;}// 链表有多个节点SLTNode* ptail = *pphead;SLTNode* prev = NULL; // 时刻更新保存 while(ptail->next){ prev = ptail;ptail = ptail->next;}prev->next = NULL;free(ptail);ptail = NULL;
}
5.2头删接口

// 链表的头删法
void SLTPopFront(SLTNode** pphead)
{assert(pphead); // 指针不能为空assert(*pphead); // 链表不能为空// 让第二个节点成为新的头节点// 将 旧的节点释放掉: 注意 要先将 第二个节点的地址  (*pphead) -> next  临时储存起来!!SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}
5.3 删除 指定位置 pos 节点 接口
// 删除pos 节点
// 删除 pos 节点后,还要 将 prev 和 next (pos的前后两个节点) 链接上!!: 比较麻烦
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead); // 指针不能为空assert(pos); // pos 不能为空assert(*pphead); // 链表不能为空: pos 是链表中 的一个有效节点,pos 不为空,链表也不能为 空//先 让 prev 链接上 next,后 free 释放掉 pos// 遇到 需要找 prev 的,一定要 检查是否存在 previf (*pphead == pos)//检查是否存在 prev{free(pos);*pphead = NULL;return;}SLTNode* prev = *pphead;while (prev->next != pos) // 找 前面节点 prev{prev = prev->next;}prev->next = pos->next; // 先赋值后 再free释放free(pos);pos = NULL;
}
 5.4 删除  指定位置 pos ==之后== 的一个 节点 接口

// 删除pos 之后的节点
// 直接 删除 pos 之后的 节点 pos->next  
// 先让 pos 和 pos -> next -> next 链接起来,后 删除 节点 pos -> next 
// 注意:像这类找 上一个节点 prev 或 找下一个节点 next :都需要 检查 是否存在 该节点
void SLTEraseBeind(SLTNode* pos)
{assert(pos); // pos 不能为空assert(pos->next); // 这个节点必须存在,否则该函数无意义! 链表至少要有两个节点// 三者的关联关系:pos    pos->next    pos->next->next// 注意:下面 先 pos->next = pos->next->next, 后 free(pos->next) 是不对的  // pos->next 已经更新,不是你所认为的原来的那个 中间节点了,因此要先 临时保存起来!!!SLTNode* temp = pos->next;pos->next = pos->next->next;free(temp);temp = NULL;
}
 6.链表的  查找  接口
// 链表的查找
SLTNode* SLTFind(SLTNode** pphead, SLDataType x)
{// 遍历链表assert(pphead); // 指针不能为空SLTNode* ptemp = *pphead;while (ptemp){if (ptemp->data == x) return ptemp; // 找到了就返回节点ptemp = ptemp->next;}// 没找到return NULL;
}
7.链表的  销毁  接口
// 销毁链表
// 一旦涉及到 动态内存申请,不要忘记销毁
void SListDestory(SLTNode** pphead)
{assert(pphead); // 指针不能为空assert(*pphead); // 链表不能为空,空的没必要销毁了// 顺序表是一段连续的空间,可以执行一次free全部销毁,而链表节点是独立的,需要遍历节点一个一个销毁// 不能直接 一个一个 free 下去,需要 保存 next 节点,才能找到下个节点!!!!SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}// 当所有节点销毁后,需要 将头指针 销毁*pphead = NULL;
}

二、总代码

SList.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>// 零、创建链表节点
typedef int SLDataType;
typedef struct SListNode
{SLDataType data;struct SListNode* next;
}SLTNode;// 一、打印函数: 这里用传址
void SLTPrint(SLTNode* ps);// 二、尾插法
void SLTPushBack(SLTNode** pphead, SLDataType x);// 三、头插法
void SLTPushFront(SLTNode** pphead, SLDataType x);// 四、尾删法
void SLTPopBack(SLTNode** pphead);// 五、头删法
void SLTPopFront(SLTNode** pphead);// 六、链表的查找
SLTNode* SLTFind(SLTNode** pphead, SLDataType x);// 七、指定位置 pos 之前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLDataType x);// 八、指定位置 pos 之后 插入
void SLTInsertAfter(SLTNode* pos, SLDataType x);// 九、删除 指定 pos 节点
void SLTErase(SLTNode** pphead, SLTNode* pos);// 十、删除指定 pos 之后 的节点
void SLTEraseAfter(SLTNode* pos);// 十一、销毁链表
void SLTDestory(SLTNode** pphead);

SList.c

#include"SList.h"// 一、打印函数: 这里用传址
void SLTPrint(SLTNode* phead)
{SLTNode* ptemp = phead;while (ptemp) //  ptemp != NULL 表示为有效节点 {printf("%d -> ", ptemp->data);ptemp = ptemp->next;}printf("NULL\n");
}// 创建节点函数
SLTNode* SLTCreatNode(SLDataType x)
{SLTNode* newNode = (SLTNode*)malloc(sizeof(SLTNode));newNode->data = x;newNode->next = NULL;return newNode;
}
// 二、尾插法
void SLTPushBack(SLTNode** pphead, SLDataType x)
{assert(pphead);// 创建新节点SLTNode* newNode = SLTCreatNode(x);// 链表为空: 没有节点 就直接插入if (*pphead == NULL){*pphead = newNode;return;}// 链表非空:找尾节点SLTNode* ptail = *pphead;while (ptail->next){ptail = ptail->next;}ptail->next = newNode;
}// 三、头插法
void SLTPushFront(SLTNode** pphead, SLDataType x)
{assert(pphead);// 创建新节点SLTNode* newNode = SLTCreatNode(x);// 先 链接 第一个节点,  没有第一个节点就是 NULL,也可以直接给 newNode->next,后更新 *ppheadnewNode->next = *pphead;*pphead = newNode;
}// 四、尾删法
void SLTPopBack(SLTNode** pphead)
{assert(pphead);assert(*pphead);// 先找尾节点 和 前置节点 prev,后删除+链接// 当只有一个 节点时if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;return;}// 当有 两个 节点 及以上SLTNode* ptail = *pphead;SLTNode* prev = NULL;while (ptail->next){prev = ptail;ptail = ptail->next;}prev->next = NULL;free(ptail);ptail = NULL;
}// 五、头删法
void SLTPopFront(SLTNode** pphead)
{assert(pphead);assert(*pphead);// 让 *pphead 指向第二个节点,free 掉第一个SLTNode* next = (*pphead)->next; // 一定要加 括号,* 号 优先级 < 箭头操作符 free(*pphead);*pphead = next;
}// 六、链表的查找
SLTNode* SLTFind(SLTNode** pphead, SLDataType x)
{assert(pphead);// 遍历SLTNode* ptemp = *pphead;while (ptemp){if (ptemp->data == x) return ptemp;ptemp = ptemp->next;}return NULL;
}// 七、指定位置 pos 之前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLDataType x)
{assert(pphead);assert(pos);assert(*pphead);// 涉及到三个节点: prev    newNode   pos// 创建新节点SLTNode* newNode = SLTCreatNode(x);if (*pphead == pos)// 无 prev 的情况{SLTPushFront(pphead, x);return;}SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}newNode->next = pos;prev->next = newNode;
}// 八、指定位置 pos 之后 插入(推荐!)
void SLTInsertAfter(SLTNode* pos, SLDataType x)
{assert(pos);// 创建新节点SLTNode* newNode = SLTCreatNode(x);newNode->next = pos->next;pos->next = newNode;
}// 九、删除 指定 pos 节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(pos);assert(*pphead);// 关系三个节点:prev    pos    next// 先找 prevSLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;
}// 十、删除指定 pos 之后 的节点
void SLTEraseAfter(SLTNode* pos)
{assert(pos);assert(pos->next); // 注意  pos->next 这个必须存在// 关系三个节点: pos      pos->next     pos->next->next// 另一种可能:     pos      pos->next     NULLif (pos->next->next == NULL){free(pos->next);pos->next = NULL;return;}// 直接销毁  pos->next  会找不到 pos->next->next,先保存SLTNode* ptemp = pos->next->next;free(pos->next);pos->next = NULL;pos->next = ptemp;
}// 十一、销毁链表
void SLTDestory(SLTNode** pphead)
{assert(pphead);// 遍历销毁if (*pphead == NULL)return;SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}// 别忘了将 头指针销毁!!!*pphead = NULL;
}

test.c

#include"SList.h"void SLTest1()
{// 零、创建 链表SLTNode* plist = NULL;// 二、尾插法SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4); // 1 -> 2 -> 3 -> 4 -> NULLprintf("测试尾插:");SLTPrint(plist);// 三、头插法SLTPushFront(&plist, 5);SLTPushFront(&plist, 6); // 6 -> 5 -> 1 -> 2 -> 3 -> 4 -> NULLprintf("测试头插:");SLTPrint(plist);// 四、尾删法SLTPopBack(&plist);SLTPopBack(&plist); // 6 -> 5 -> 1 -> 2 -> NULLprintf("测试尾删:");SLTPrint(plist);// 五、头删法SLTPopFront(&plist);SLTPopFront(&plist); // 1 -> 2 -> NULLprintf("测试头删:");SLTPrint(plist);// 六、链表的查找SLTNode* FindRet = SLTFind(&plist, 2);printf("测试查找:");if (FindRet) printf("找到了\n");else printf("没找到\n");// 七、指定位置 pos 之前插入SLTNode* FindRet1 = SLTFind(&plist, 2);SLTNode* FindRet2 = SLTFind(&plist, 1);SLTInsert(&plist, FindRet1, 200);SLTInsert(&plist, FindRet2, 100);// 100 -> 1 -> 200 -> 2 -> NULLprintf("测试指定位置之前插入:");SLTPrint(plist);// 八、指定位置 pos 之后 插入(推荐!)SLTNode* FindRet3 = SLTFind(&plist, 2);SLTInsertAfter(FindRet3, 200); // 100 -> 1 -> 200 -> 2 -> 200 -> NULLprintf("测试指定位置之后插入:");SLTPrint(plist);// 九、删除 指定 pos 节点SLTNode* FindRet4 = SLTFind(&plist, 1);SLTErase(&plist, FindRet4);// 100 -> 200 -> 2 -> 200 -> NULLprintf("测试删除指定节点:");  SLTPrint(plist);// 十、删除指定 pos 之后 的节点SLTNode* FindRet5 = SLTFind(&plist, 200); // 注意如果 通过 Find 函数 找 节点,节点中有重复数据,返回 第一个遇到的SLTEraseAfter(FindRet5);// 100 -> 200 -> 200 -> NULLprintf("测试删除指定节点:"); SLTPrint(plist);//
}
int main()
{SLTest1();return 0;
}

完。

若上述文章有什么错误,欢迎各位大佬及时指出,我们共同进步!

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

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

相关文章

【无标题】yarn报错 “https://registry.npm.taobao.org/...: certificate has expired“如何处理

前言 今天在jenkins打包项目时yarn打包报错&#xff0c;查看log发现npm淘宝镜像报错 原因 在 1 月 22 日&#xff0c;淘宝原镜像域名&#xff08;registry.npm.taobao.org&#xff09;的 HTTPS 证书正式到期。如果想要继续使用&#xff0c;需要将 npm 源切换到新的源&#…

Dockerfile构建Nginx访问说明

Dockerfile使用情况 20210903 Dockerfile ,Nginx 参考地址&#xff1a;https://yeasy.gitbook.io/docker_practice/image/build 编写简单Dockerfile 在一个空白目录中&#xff0c;建立一个文本文件&#xff0c;并命名为 Dockerfile&#xff1a; $ mkdir mynginx $ cd myngin…

跟着cherno手搓游戏引擎【18】抽象Shader、项目小修改

抽象&#xff1a; Shader.h: #pragma once #include <string>namespace YOTO {class Shader {public:virtual~Shader()default;virtual void Bind()const0;virtual void UnBind()const0;static Shader* Create(const std::string& vertexSrc, const std::string&am…

window 安装 jenkins 编写脚本

set JAVA_HOMED:\RuanJianKaiFa\jdk\jdk11 set CLASSPATH.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOMe%\lib\tools.jar; set Path%JAVA_HOME%\bin; java -jar jenkins.war 下载jenkins.war包&#xff0c;编写一个txt文档&#xff0c;把脚本复制进去&#xff0c;修改文件后缀为.bat文件…

MySQL EXPLAIN查询执行计划

EXPLAIN 可用来查看SQL执行计划&#xff0c;常用来分析调试SQL语句&#xff0c;来使SQL语句达到更好的性能。 1 前置知识 在学习EXPLAIN 之前&#xff0c;有些基础知识需要清楚。 1.1 JSON类型 MySQL 5.7及以上版本支持JSON数据类型。可以将数组存为JSON格式的字符串&#…

本体匹配方法概述

目录 前言1 基于术语匹配的方法1.1 字符串匹配1.2 语言方法 2 基于虚拟文档的方法3 基于结构的匹配方法3.1 结构信息利用3.2 Anchor-prompt方法 4 大型本体匹配4.1 本体划分4.2 匹配分块4.3 实体间映射 结语 前言 本文将深入探讨本体匹配的不同方法&#xff0c;从基于术语匹配…

DES加密原理

DES加密算法综合运用了置换、代替、代数等多种密码技术&#xff0c;具有设计精 巧、实现容易、使用方便等特点。DES加密算法的明文、密文和密钥的分组长度 都是64位&#xff0c;详细的DES加密算法结构如图6-10所示。 图6-10 DES加密算法结构图 DES加密过程如下所示&#xff…

2024PMP考试新考纲-【业务环境领域】典型真题和很详细解析(3)

华研荟继续分享【业务环境Business Environment领域】在新考纲下的真题&#xff0c;帮助大家体会和理解新考纲下PMP的考试特点和如何应用所学的知识和常识&#xff08;经验&#xff09;来解题&#xff0c;并且举一反三&#xff0c;一次性3A通过2024年PMP考试。 2024年PMP考试新…

0202-1-处理机调度与死锁

第三章:处理机调度与死锁 处理机调度算法的目标 处理机调度算法的共同目标 资源利用率:CPU的利用率CPU有效工作时间/(CPU有效工作时间CPU空闲等待时间)公平性平衡性策略强制执行 批处理系统的目标 平均周转时间短系统吞吐量高处理机利用率高 分时系统的目标 响应时间快均…

10MHz 到 80MHz、10:1 LVDS 并串转换器(串化器)/串并转换器(解串器)MS1023/MS1224

产品简述 MS1023 串化器和 MS1224 解串器是一对 10bit 并串 / 串并转 换芯片&#xff0c;用于在 LVDS 差分底板上传输和接收 10MHz 至 80MHz 的并行字速率的串行数据。起始 / 停止位加载后&#xff0c;转换为负载编 码输出&#xff0c;串行数据速率介于 120Mbps…

如何将 h5 页面快速转换成微信小程序

Hello各位朋友们大家新的一月好呀&#xff01;我是咕噜铁蛋&#xff01;我知道在小程序开发中&#xff0c;有时候需要将H5页面转换成微信小程序页面。这样可以将原本的网页内容适配到小程序中&#xff0c;让用户能够更方便地访问和使用。在本文中&#xff0c;我将分享如何快速将…

Vue实现公告循环横向播报组件

一、代码组件 注意&#xff1a;当公告字数很少时会固定不动&#xff0c;当字数达到最大宽度时&#xff0c;则会循环播报 <template><div class"TopCard"><!-- 小喇叭 --><div style"width: 70px"><notify style"width: 2…

git小白进阶之路

git是最常用的版本控制工具&#xff0c;我对其进行了整理后续补充&#xff0c;这个文档欢迎大家来讨论&#xff0c;当前我的视频梳理&#xff1a; git小白进阶之路_哔哩哔哩_bilibili&#xff0c;非常希望大佬们能够批评指正&#xff0c;并多多交流。 目录 初始配置 配置账号…

《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述(5)

接前一篇文章&#xff1a;《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述&#xff08;4&#xff09; 4.1.2 PCIe总线使用的信号 PCIe设备使用两种电源信号供电&#xff0c;分别是Vcc与Vaux&#xff0c;其额定电压为3.3V。其中Vcc为主电源&#xff0c;PCIe设备…

上位机图像处理和嵌入式模块部署(linux开发板的选择)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很多图像算法是通过上位机来完成的&#xff0c;比如说工业视觉当中的halcon&#xff0c;一般都是要运行在windows平台上面&#xff0c;并且需要高性…

Fashion MNIST数据集介绍及基于Pytorch下载数据集

Fashion MNIST数据集介绍及基于Pytorch下载数据集 &#x1f335;文章目录&#x1f335; &#x1f333;引言&#x1f333;&#x1f333;Fashion MNIST数据集简介&#x1f333;Fashion MNIST数据集的类别说明Fashion MNIST数据集图片示例 &#x1f333;基于PyTorch下载Fashion MN…

卸载Ubuntu双系统

卸载Ubuntu双系统 我们卸载Ubuntu双系统&#xff0c;可能出于以下原因&#xff1a; 1、Ubuntu系统内核损坏无法正常进入 2、Ubuntu系统分配空间不足&#xff0c;直接扩区较为复杂 3、以后不再使用Ubuntu&#xff0c;清理留出空间 123无论出于哪种原因&#xff0c;我们都是要…

Python调取Excel数据类似VLOOKUP

当需要通过某一信息&#xff0c;获取表格中其他信息时&#xff0c;比如想通过学号&#xff0c;直接拉取该学生的其他表格信息 可以通过如下代码&#xff1a; import xlrd #xlrd 常用的Excel读取库file "test.xls" #文件地址&#xff0c;注意xlrd可能无法…

【Android新版本兼容】onBackPressed()方法被弃用的解决方案

提示&#xff1a;此文章仅作为本人记录日常学习使用&#xff0c;若有存在错误或者不严谨得地方欢迎指正。 文章目录 一、使用 AndroidX API 实现预测性返回手势1.1 添加依赖1.2 启用返回手势1.3 注册OnBackPressedCallback()方法来处理返回手势 一、使用 AndroidX API 实现预测…

Vue3_基础使用_2

这节主要介绍&#xff1a;标签和组件的ref属性&#xff0c;父子组件间的传递值&#xff0c;ts的接口定义&#xff0c;vue3的生命周期 1.标签的ref属性。 1.1ref属性就是给标签打标识用的&#xff0c;相当于html的id&#xff0c;但是在vue3中用id可能会乱&#xff0c;下面是ref…