基于单链表实现通讯管理系统!(有完整源码!)
个人主页:秋风起,再归来~
文章专栏:C语言实战项目
个人格言:悟已往之不谏,知来者犹可追
克心守己,律己则安!
1、前言
友友们,这篇文章是基于单链表来实现通讯管理系统的,所以一定要先看完我之前写过的一篇关于单链表的实现(文章链接)的文章哦~
其实基于单链表实现通讯录的思路与基于顺讯表实现通讯录的思路是一样的,在这里我就不进行赘述了。如果还没有看过我之前写的一篇基于顺序表实现通讯录(文章链接)的宝子们一定要去看看哦~
2、各种接口的实现
以下是我们希望实现的接口~
//contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100//前置声明
typedef struct SListNode contact;//用户数据
typedef struct PersonInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}PeoInfo;//初始化通讯录
void InitContact(contact** con);//添加通讯录数据
void AddContact(contact** con);//展示通讯录数据
void ShowContact(contact* con);//删除通讯录数据
void DelContact(contact** con);//查找通讯录数据
void FindContact(contact* con);//修改通讯录数据
void ModifyContact(contact** con);//销毁通讯录数据
void DestroyContact(contact** con);
2.1 初始化通讯录
我们希望在初始化通讯录时导入之前我们原有文件中的数据,那我们就可以进行如下的操作~
//从文件中导入原数据
void DLoadContact(contact** con)
{FILE* pf = fopen("contact.txt", "rb");if (pf == NULL){perror("open fail\n");return;}PeoInfo p = { 0 };while (fread(&p, sizeof(PeoInfo),1,pf)){SListPushBack(con, p);}printf("历史数据导入成功!\n");fclose(pf);pf = NULL;
}
在初始化通讯录之后加载数据!
//初始化通讯录
void InitContact(contact** con)
{assert(con);(*con) = NULL;DLoadContact(con);
}
2.2 添加通讯录数据
//添加通讯录数据
void AddContact(contact** con)
{assert(con);PeoInfo p = {0};printf("请输入添加联系人的姓名:");scanf("%s", p.name);printf("请输入添加联系人的性别:");scanf("%s", p.sex);printf("请输入添加联系人的年龄:");scanf("%d", &(p.age));printf("请输入添加联系人的电话:");scanf("%s", p.tel);printf("请输入添加联系人的住址:");scanf("%s", p.addr);SListPushBack(con,p);printf("\n");
}
2.3 删除通讯录数据
在查找通讯录数据之外封装一个函数(findByName)来通过名字查找联系人!
(因为我们在之后的查找和修改接口中都会用到这个方法,所以我们把它封装成一个函数方便我们后续的使用!)
//通过名字查找联系人
contact* findByName(contact* con,char* name)
{assert(con);contact* cur = con;while (cur){if (strcmp(cur->data.name, name) == 0){return cur;}cur = cur->next;}return NULL;
}
在原有单链表的删除指定数据的接口上进行封装(让单链表摇身一变成为通讯录!)
//删除通讯录数据
void DelContact(contact** con)
{assert(con && (*con));char name[NAME_MAX];printf("请输入你要删除的联系人的名字:");scanf("%s", name);contact* pos = findByName(*con,name);if (pos == NULL){printf("您要删除的联系人不存在!\n");return;}SListErase(con, pos);printf("删除成功!\n");
}
2.4 展示通讯录数据
遍历我们的通讯录打印信息!
//展示通讯录数据
void ShowContact(contact* con)
{assert(con);contact* cur = con;printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头while (cur){printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",cur->data.name,cur->data.sex,cur->data.age,cur->data.tel,cur->data.addr);cur = cur->next;}
}
2.5 查找通讯录数据
//通过名字查找联系人
contact* findByName(contact* con,char* name)
{assert(con);contact* cur = con;while (cur){if (strcmp(cur->data.name, name) == 0){return cur;}cur = cur->next;}return NULL;
}
在接口内部调用该函数!
//查找通讯录数据
void FindContact(contact* con)
{assert(con);char name[NAME_MAX];printf("请输入你要查找的联系人的名字:");scanf("%s", name);contact* ret = findByName(con, name);if (ret == NULL){printf("您要查找的联系人不存在!\n");return;}printf("找到了!\n");printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",ret->data.name,ret->data.sex,ret->data.age,ret->data.tel,ret->data.addr);
}
2.6 修改通讯录数据
//通过名字查找联系人
contact* findByName(contact* con,char* name)
{assert(con);contact* cur = con;while (cur){if (strcmp(cur->data.name, name) == 0){return cur;}cur = cur->next;}return NULL;
}
在接口内部调用该函数!
//修改通讯录数据
void ModifyContact(contact** con)
{assert(con);char name[NAME_MAX];printf("请输入你要修改的联系人的名字:");scanf("%s", name);contact* ret = findByName(*con, name);if (ret == NULL){printf("您要修改的联系人不存在!\n");return;}PeoInfo p = { 0 };printf("请输入修改后联系人的姓名:");scanf("%s", p.name);printf("请输入修改后联系人的性别:");scanf("%s", p.sex);printf("请输入修改后加联系人的年龄:");scanf("%d", &(p.age));printf("请输入修改后联系人的电话:");scanf("%s", p.tel);printf("请输入修改后联系人的住址:");scanf("%s", p.addr);SListModify(ret, p);printf("修改成功!\n");
}
2.7 销毁通讯录数据
因为我们希望在退出通讯管理系统的时候可以将我们的操作都保留下来,所以我们可以对其进行文件操作!
//将输入的数据保存到文件中
void SaveContact(contact** con)
{FILE* pf = fopen("contact.txt", "wb");if (pf == NULL){perror("open fail!\n");return;}contact* cur = *con;while (cur){fwrite(&(cur->data), sizeof(PeoInfo), 1, pf);cur = cur->next;}printf("历史数据保存成功!\n");fclose(pf);pf = NULL;
}
在销毁通讯录之前保留数据!
//销毁通讯录数据
void DestroyContact(contact** con)
{SaveContact(con);SListDestroy(con);
}
3、完整源码
SeqList.h
#pragma once//避免头文件被多次引用
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Contact.h"
typedef PeoInfo SListDataType;//便于改变数据类型//定义一个结构体类型的节点
typedef struct SListNode
{SListDataType data;struct SListNode* next;//存储下一个节点的地址
}SListNode;//1. 新节点的创建
SListNode* SListCreatNode(SListDataType x);//2. 打印单链表
void PrintSList(SListNode* phead);//3. 头插
void SListPushFront(SListNode** phead, SListDataType x);//4. 头删
void SListPopFront(SListNode** phead);//5. 尾差
void SListPushBack(SListNode** phead, SListDataType x);//6. 尾删
void SListPopBack(SListNode** phead);//7. 查找元素X
SListNode* SListFind(SListNode* phead, SListDataType x);//8. 在pos位置修改
void SListModify(SListNode* pos, SListDataType x);//9. 在任意位置之前插入
void SListInsert(SListNode** phead, SListNode* pos, SListDataType x);//10. 在任意位置删除
void SListErase(SListNode** phead, SListNode* pos);//11. 销毁单链表
void SListDestroy(SListNode** phead);
Contact.h
#define _CRT_SECURE_NO_WARNINGS//contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100//前置声明
typedef struct SListNode contact;//用户数据
typedef struct PersonInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}PeoInfo;//初始化通讯录
void InitContact(contact** con);//添加通讯录数据
void AddContact(contact** con);//展示通讯录数据
void ShowContact(contact* con);//删除通讯录数据
void DelContact(contact** con);//查找通讯录数据
void FindContact(contact* con);//修改通讯录数据
void ModifyContact(contact** con);//销毁通讯录数据
void DestroyContact(contact** con);
SeqList.c
#include"SList.h"//1. 新节点的创建
SListNode* SListCreatNode(SListDataType x)
{SListNode* NewNode = (SListNode*)malloc(sizeof(SListNode));//开辟空间if (NewNode == NULL)//判断空间是否开辟成功{perror("malloc fail");return NULL;}NewNode->data = x;//赋值NewNode->next = NULL;//置空return NewNode;
}#if 0
//2. 打印单链表
void PrintSList(SListNode* phead)
{if (phead == NULL){printf("NULL");//如果链表没有元素就打印NULLreturn;}SListNode* cur = phead;//循环单链表打印while (cur != NULL){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}
#endif//3. 头插
void SListPushFront(SListNode** phead, SListDataType x)
{assert(phead);SListNode* newnode = SListCreatNode(x);//创建一个新节点newnode->next = *phead;*phead = newnode;
}//4. 头删
void SListPopFront(SListNode** phead)
{assert(phead);assert(*phead);//如果没有数据就不用头删,并报错SListNode* cur = (*phead)->next;free(*phead);*phead = cur;
}//5. 尾插
void SListPushBack(SListNode** phead, SListDataType x)
{assert(phead);if (*phead == NULL){*phead = SListCreatNode(x);//创建新节点并插入}else{SListNode* tail = *phead;while (tail->next != NULL)//找到尾节点{tail = tail->next;}tail->next = SListCreatNode(x);//创建新节点并插入}
}//6. 尾删
void SListPopBack(SListNode** phead)
{assert(phead);assert(*phead);//链表为空就不进行尾删SListNode* tail = *phead;if (tail->next == NULL)//如果链表就只有一个元素就进行头删{SListPopFront(phead);}else{while (tail->next->next != NULL){tail = tail->next;}free(tail->next);tail->next = NULL;}
}#if 0
//7. 查找元素X
SListNode* SListFind(SListNode* phead, SListDataType x)
{assert(phead);while (phead->next != NULL)//注意最后一个节点是没有查找的{if (phead->data == x)return phead;phead = phead->next;}if (phead->data == x)return phead;//最后一个节点没有查找elsereturn NULL;//没找到
}
#endif//8. 在pos位置修改
void SListModify(SListNode* pos, SListDataType x)
{assert(pos);pos->data = x;
}//9. 在任意位置之前插入
void SListInsert(SListNode** phead, SListNode* pos, SListDataType x)
{assert(phead);assert(*phead);if (pos == *phead)//如果pos位置刚好是第一个节点就进行头插{SListPushFront(phead, x);}else{SListNode* newnode = SListCreatNode(x);SListNode* cur = *phead;while (cur->next != pos)//找到pos前一个节点{cur = cur->next;}cur->next = newnode;newnode->next = pos;}
}//10. 在任意位置删除
void SListErase(SListNode** phead, SListNode* pos)
{assert(phead && *phead && pos);if (pos == *phead)//如果pos位置就是第一个节点就进行头删{SListPopFront(phead);}else{SListNode* cur = *phead;while (cur->next != pos)//找到pos前一个节点{cur = cur->next;}cur->next = pos->next;free(pos);}
}//11. 销毁单链表
void SListDestroy(SListNode** phead)
{assert(*phead && phead);SListNode* cur = *phead;while (cur != NULL){SListNode* tmp = cur->next;free(cur);cur = tmp;}*phead = NULL;
}
Contact.c
#include"SList.h"//从文件中导入原数据
void DLoadContact(contact** con)
{FILE* pf = fopen("contact.txt", "rb");if (pf == NULL){perror("open fail\n");return;}PeoInfo p = { 0 };while (fread(&p, sizeof(PeoInfo),1,pf)){SListPushBack(con, p);}printf("历史数据导入成功!\n");fclose(pf);pf = NULL;
}//初始化通讯录
void InitContact(contact** con)
{assert(con);(*con) = NULL;DLoadContact(con);
}//添加通讯录数据
void AddContact(contact** con)
{assert(con);PeoInfo p = {0};printf("请输入添加联系人的姓名:");scanf("%s", p.name);printf("请输入添加联系人的性别:");scanf("%s", p.sex);printf("请输入添加联系人的年龄:");scanf("%d", &(p.age));printf("请输入添加联系人的电话:");scanf("%s", p.tel);printf("请输入添加联系人的住址:");scanf("%s", p.addr);SListPushBack(con,p);printf("\n");
}//展示通讯录数据
void ShowContact(contact* con)
{assert(con);contact* cur = con;printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头while (cur){printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",cur->data.name,cur->data.sex,cur->data.age,cur->data.tel,cur->data.addr);cur = cur->next;}
}//通过名字查找联系人
contact* findByName(contact* con,char* name)
{assert(con);contact* cur = con;while (cur){if (strcmp(cur->data.name, name) == 0){return cur;}cur = cur->next;}return NULL;
}//删除通讯录数据
void DelContact(contact** con)
{assert(con && (*con));char name[NAME_MAX];printf("请输入你要删除的联系人的名字:");scanf("%s", name);contact* pos = findByName(*con,name);if (pos == NULL){printf("您要删除的联系人不存在!\n");return;}SListErase(con, pos);printf("删除成功!\n");
}//查找通讯录数据
void FindContact(contact* con)
{assert(con);char name[NAME_MAX];printf("请输入你要查找的联系人的名字:");scanf("%s", name);contact* ret = findByName(con, name);if (ret == NULL){printf("您要查找的联系人不存在!\n");return;}printf("找到了!\n");printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",ret->data.name,ret->data.sex,ret->data.age,ret->data.tel,ret->data.addr);
}//修改通讯录数据
void ModifyContact(contact** con)
{assert(con);char name[NAME_MAX];printf("请输入你要修改的联系人的名字:");scanf("%s", name);contact* ret = findByName(*con, name);if (ret == NULL){printf("您要修改的联系人不存在!\n");return;}PeoInfo p = { 0 };printf("请输入修改后联系人的姓名:");scanf("%s", p.name);printf("请输入修改后联系人的性别:");scanf("%s", p.sex);printf("请输入修改后加联系人的年龄:");scanf("%d", &(p.age));printf("请输入修改后联系人的电话:");scanf("%s", p.tel);printf("请输入修改后联系人的住址:");scanf("%s", p.addr);SListModify(ret, p);printf("修改成功!\n");
}//将输入的数据保存到文件中
void SaveContact(contact** con)
{FILE* pf = fopen("contact.txt", "wb");if (pf == NULL){perror("open fail!\n");return;}contact* cur = *con;while (cur){fwrite(&(cur->data), sizeof(PeoInfo), 1, pf);cur = cur->next;}printf("历史数据保存成功!\n");fclose(pf);pf = NULL;
}
//销毁通讯录数据
void DestroyContact(contact** con)
{SaveContact(con);SListDestroy(con);
}
这里我就没有单独去写一个菜单了,本身的意义也并不大,但是如果友友们想写一个来玩一玩,可以看看我之前那篇基于顺序表实现通讯录(文章链接),那里有菜单的模版(只要改几个接口的名字就行了)~
4、 完结散花
好了,这期的分享到这里就结束了~
如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~
如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~
我们下期不见不散~~
相关文章:
基于单链表实现通讯管理系统!(有完整源码!)
个人主页:秋风起,再归来~ 文章专栏:C语言实战项目 个人格言:悟已往之不谏,知来者犹可追 克心守己,律己则安! 1、前言 友友们,这篇文章是基于单链…...
MATLAB入门介绍
MATLAB是由MathWorks公司开发的一款专业的数学计算软件,主要用于算法开发、数据可视化、数据分析以及数值计算等领域。它提供了一个易于使用的环境,让用户可以通过矩阵计算、函数和数据绘图、用户界面的创建以及编程和文档编写来解决各种数学问题。 MATL…...
【k8s】:深入理解 Kubernetes 中的污点(Taints)与容忍度(Tolerations)
【k8s】:深入理解 Kubernetes 中的污点(Taints)与容忍度(Tolerations) 1、污点(Taints)2、容忍度(Tolerations)3、示例演示-测试污点的具体应用场景3.1 给节点打污点&…...
Angular 使用DomSanitizer防范跨站脚本攻击
跨站脚本Cross-site scripting 简称XSS,是代码注入的一种,是一种网站应用程序的安全漏洞攻击。它允许恶意用户将代码注入到网页上,其他用户在使用网页时就会收到影响,这类攻击通常包含了HTML和用户端脚本语言(JS&…...
(八)PostgreSQL的数据库管理
PostgreSQL的数据库管理 基础信息 OS版本:Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本:16.2 pg软件目录:/home/pg16/soft pg数据目录:/home/pg16/data 端口:57771 创建数据库 CREATE DATABASE创建一…...
外包干了30天,技术倒退明显
先说情况,大专毕业,18年通过校招进入湖南某软件公司,干了接近6年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能…...
ruoyi-nbcio-plus基于vue3的flowable的自定义业务单表例子的升级修改
更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码:…...
【ENSP】华为三层交换机配置AAA认证,开启telnet服务
配置步骤 1.给交换机配置ip地址,以便登陆 2.配置AAA,用户名,密码,服务类型,用户权限 3.配置接入设备的数量 4.开启telnet服务 LSW2交换机配置 u t m #关闭提示 sys …...
collections模块下的Counter函数讲解
📚博客主页:knighthood2001 ✨公众号:认知up吧 (目前正在带领大家一起提升认知,感兴趣可以来围观一下) 🎃知识星球:【认知up吧|成长|副业】介绍 ❤️感谢大家点赞👍&…...
HarmonyOS开发实例:【分布式邮件】
概述 基于TS扩展的声明式开发范式编程语言编写的一个分布式邮件系统,可以由一台设备拉起另一台设备,每次改动邮件内容,都会同步更新两台设备的信息。效果图如下: 搭建OpenHarmony开发环境 完成本篇Codelab我们首先要完成开发环境…...
llama2.c与chinese-baby-llama2语言模型本地部署推理
文章目录 简介Github文档克隆源码英文模型编译运行中文模型(280M)main函数 简介 llama2.c是一个极简的Llama 2 LLM全栈工具,使用一个简单的 700 行 C 文件 ( run.c ) 对其进行推理。llama2.c涉及LLM微调、模型构建、推理端末部署(…...
008、Python+fastapi,第一个后台管理项目走向第8步:ubutun 20.04下安装vscode+python环境配置
一、说明 白飘了3个月无影云电脑,开始选了个windows server 非常不好用,后台改为ubuntu想升级到22,没成功,那就20.04吧。 今天先安装下开发环境,后续2个月就想把他当做开发服务器,不知道行不行,…...
2024.4.16 驱动开发
思维导图...
如何在 Ubuntu 14.04 上更改 PHP 设置
简介 PHP 是一种服务器端脚本语言,被许多流行的 CMS 和博客平台如 WordPress 和 Drupal 所使用。它也是流行的 LAMP 和 LEMP 堆栈的一部分。更新 PHP 配置设置是设置基于 PHP 的网站时的常见任务。定位确切的 PHP 配置文件可能并不容易。通常在服务器上会有多个 PH…...
【光伏企业】光伏项目怎么做才能提高效率?
一、精细化项目管理 项目规划:在项目启动前,进行充分的调研和规划,明确项目的目标、规模、预算和时间表,确保各项资源得到合理分配。 团队建设:组建一支高效、专业的项目团队,确保团队成员具备光伏领域的…...
毕设选51还是stm32?51太简单?
如果你更倾向于挑战和深入学习,STM32可能是更好的选择。如果你希望更专注于底层硬件原理,51可能更适合。我这里有一套嵌入式入门教程,不仅包含了详细的视频讲解,项目实战。如果你渴望学习嵌入式,不妨点个关注ÿ…...
ip addr和ifconfig区别
ip addr和ifconfig都是用于配置和管理网络接口的工具 1. ifconfig ifconfig是较旧的网络配置工具,属于net-tools套件的一部分。 该命令主要用于配置、显示和控制网络接口的参数,如IP地址、子网掩码、广播地址等。 ifconfig命令的功能相对有限ÿ…...
Springboot+Vue项目-基于Java+MySQL的房产销售系统(附源码+演示视频+LW)
大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:Java毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计 &…...
向量数据库中的向量是什么?
在向量数据库中,向量通常指的是高维空间中的点或方向,它们由一组数值组成,这些数值表示该点在空间中的位置或方向。在机器学习和人工智能领域,向量经常用于表示各种类型的数据,如文本、图像、音频等。 具体来说&#x…...
【重回王座】ChatGPT发布最新模型gpt-4-turbo-2024-04-09
今天,新版GPT-4 Turbo再次在大型模型排行榜上荣登榜首,成功超越了此前领先的Claude 3 Opus。另外,新模型在处理长达64k的上下文时,性能竟能够与旧版在处理26k上下文时的表现相当。 目前GPT-4 Turbo仅限于ChatGPT Plus的用户&…...
Funannotate数据库安装终极指南:解决HPC环境中的常见问题
Funannotate数据库安装终极指南:解决HPC环境中的常见问题 【免费下载链接】funannotate Eukaryotic Genome Annotation Pipeline 项目地址: https://gitcode.com/gh_mirrors/fu/funannotate Funannotate作为一款专业的真核生物基因组注释流程工具,…...
Unity性能优化实战:Mesh Baker 纹理合并与UV重映射详解
1. 为什么需要纹理合并与UV重映射 在开发开放世界游戏时,场景中往往会出现大量重复的建筑、植被等模型。每个模型通常都有自己的材质球和贴图,这会导致两个严重问题:首先是Draw Call数量激增,每个材质球都会产生一次Draw Call&…...
FastAPI部署演进:从Gunicorn+Uvicorn镜像到原生多进程的迁移指南
1. 项目背景与演进:从“黄金搭档”到“历史遗产”如果你在过去几年里用 FastAPI 部署过 Web 服务,大概率听说过或者用过tiangolo/uvicorn-gunicorn-fastapi-docker这个 Docker 镜像。它一度是 FastAPI 官方文档里推荐的部署方案之一,由 FastA…...
2026年5月PLC厂家:十大品牌专业评测解决工厂自动化选型难
摘要当制造业加速迈向智能化和柔性生产,PLC作为工业自动化的核心控制单元,其选型直接决定了产线效率、系统稳定性与长期运营成本。然而,面对众多品牌在技术路线、开放程度、生态兼容性上的显著分化,决策者常陷入“性能与成本如何平…...
AI应用着陆页模板:快速构建专业产品门户的实战指南
1. 项目概述:一个面向AI应用落地的着陆页模板 最近在折腾AI应用开发的朋友,估计都遇到过同一个问题:模型和算法好不容易调好了,后端API也搭起来了,但一到“怎么让用户用起来”这一步,就卡壳了。尤其是那个…...
DeepSeek(V3为主、兼顾V2/R1)算力优化细节详解
DeepSeek(V3为主、兼顾V2/R1)算力优化细节详解以下是针对核心优化模块的深入技术拆解,包含MLA数学原理、FP8精准实现、无辅助损失负载均衡、R1-GRPO算法核心,内容基于DeepSeek-V3官方技术报告及2026年5月公开权威分析。DeepSeek系…...
别再折腾Anaconda了!用PyCharm 2024.1自带工具5分钟搞定TensorFlow 2.15 + Keras 3环境
PyCharm 2024.1极简指南:5分钟无痛部署TensorFlow 2.15 Keras 3深度学习环境 深度学习环境配置曾是无数开发者的噩梦——直到PyCharm 2024.1彻底改变了游戏规则。最新版本集成的环境管理工具让TensorFlow和Keras的安装变得像点外卖一样简单,完全跳过了传…...
鸿蒙系统安装
一、下载 DevEco Studio 打开华为开发者官网,找到 DevEco Studio 6.1.0 Release 下载页面。 DevEco Studio for Windows 6.1.0.830(2.8GB) 下载。 Mac 用户可以选择对应版本(x86/ARM)。 等待下载完成,得到 .exe 安装文件。二、安装…...
Windows平台ADB驱动终极安装指南:3分钟搞定Android开发环境
Windows平台ADB驱动终极安装指南:3分钟搞定Android开发环境 【免费下载链接】Latest-adb-fastboot-installer-for-windows A Simple Android Driver installer tool for windows (Always installs the latest version) 项目地址: https://gitcode.com/gh_mirrors/…...
自组织映射(SOM):无监督拓扑保持的高维数据可视化与聚类
1. 什么是自组织映射(SOM)?它到底能帮你解决什么实际问题?我第一次在客户现场看到SOM落地,是在一家做工业设备预测性维护的公司。他们有上百台传感器,每台每秒产生十几维的振动、温度、电流数据,…...

