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

数据结构C语言描述8(图文结合)--哈希、哈希冲突、开放地址法、链地址法等实现

前言

  • 这个专栏将会用纯C实现常用的数据结构和简单的算法;
  • 有C基础即可跟着学习,代码均可运行;
  • 准备考研的也可跟着写,个人感觉,如果时间充裕,手写一遍比看书、刷题管用很多,这也是本人采用纯C语言实现的原因之一;
  • 欢迎收藏 + 关注,本人将会持续更新。

文章目录

    • 什么是哈希
    • 哈希构造函数
    • 哈希解决冲突方法
      • 开放地址寻址法
      • 链地址法
    • 数组哈希案例实现
      • 封装
      • 创建哈希
      • 得到哈希映射值
      • 插入数据
      • 哈希查找
      • 总代码
    • 链表哈希案例实现
      • 封装
      • 插入
      • 查找
      • 总代码

什么是哈希

📘 概念:哈希结构(Hash Table)也被称为散列表,是一种用于实现字典(Dictionary)的数据结构。

重点:散列表,这个刷过算法的人应该都知道这个数据结果,散列表的特点就是查找特别快典型应用:判断A集合是否存在B集合;字典结构,我感觉学过Python或者JS都很清楚这个特点了;

🔴 重点概念

  • 哈希结构通过键Key映射到值Value的过程称为哈希映射学过数学应该都知道这个概念,函数就是典型的映射关系;
  • 哈希函数:将映射到一个存储位置的函数;

用处

哈希用处很多,最核心的应用是查找,哈希查找速度很快,如:用数组作为哈希结构容器,假设我们要存储一段数据(1, 5, 100, 10000, 100000),想要查找最快,找到数组下标即可但是这个最大值很大(100000),如果申请这么大的内存,储存量却很少,这就造成了内存浪费,但是用哈希结构的一些方法,可以很大的节省时间数组也是一种哈希结构,这个后面我们会讲。

哈希构造函数

🏡 概念 哈希构造函数(Hash Constructor)是哈希结构中的一种函数,用于将键(Key)映射到哈希表中的位置。哈希构造函数通常是一个确定性函数,即对于相同的键,哈希构造函数总是返回相同的哈希值。哈希构造函数的设计非常关键,它直接影响哈希结构的查找、插入和删除等操作的效率。

重点

  • 哈希函数:将键值映射到哈希表中位置;
  • 哈希构造函数通常是一个确定性函数,即对于相同的键,哈希构造函数总是返回相同的哈希值,键与射的值相互对于,具有唯一性
  • 哈希构造函数的设计非常关键,但是这个一般我感觉需要结合业务场景,根据不同数据从而选取不同的哈希函数,下面会有一些常用的哈希函数。

🌓 哈希构造函数的设计需要满足以下几个要求:

  • 一致性:对于相同的键,哈希构造函数应该总是返回相同的哈希值。
  • 均匀性:哈希构造函数应该尽可能均匀地将键映射到哈希表中的位置,以避免哈希冲突。
  • 高效性:哈希构造函数的计算时间应该尽可能短,以提高哈希结构的操作效率。

🌌 哈希构造函数的设计方法有很多种,常见的方法包括:

  • 直接寻址法(Direct Addressing):将键直接作为哈希表中的位置,适用于键的范围比较小的情况。

  • 除留余数法(Division Method):将键除以一个不大于哈希表大小的质数,然后取余数作为哈希值,h*(*k)= k mod mm 是哈希表的大小,即输出哈希值的范围,这个也是最常用的,一般来说,m不能过于靠近2的幂

  • 乘法哈希法(Multiplicative Hashing):将键乘以一个常数A(0<A<1),然后取乘积的小数部分乘以哈希表大小作为哈希值。

    在这里插入图片描述

  • 一次探测法(Linear Probing):当发生哈希冲突时,依次向后探测空桶,直到找到空桶或者遍历整个哈希表。

  • 双重哈希法(Double Hashing):使用两个不同的哈希函数,当发生哈希冲突时,依次使用两个哈希函数计算出新的哈希值,直到找到空桶或者遍历整个哈希表。

🌾 当然还有其他,注意:像除留余数法,为什么需要除以不大于哈希表最大大小的质数,这是是有严格的数学证明,可以减少哈希冲突概率,记住即可。

哈希解决冲突方法

这个有很多,如:开放地址寻址法、再次哈希法、链地址法、建立公共溢出区,这里只讲解,开放地址寻址法和链地址法。

开放地址寻址法

开发地址寻址法就是在发生哈希冲突的时候,在哈希映射那个点往后寻找,寻找到一个空位即可。

在这里插入图片描述

在这里插入图片描述

链地址法

链地址法就是用一个链表,当发生哈希冲突的时候,在哈希映射那个位置,拉一条链表,将数据填入链表中。

在这里插入图片描述

数组哈希案例实现

封装

// 这里假设存储的数据是这个,key是自己抽象出来的
typedef struct Data {int key;char buffer[20];
}Data;typedef struct Hash {Data** data;int p;int count;
}Hash;

创建哈希

Hash* create_hash(int p)
{Hash* hash = (Hash*)calloc(1, sizeof(Hash));assert(hash);hash->data = (Data**)calloc(p, sizeof(Data));assert(hash->data);hash->p = p;return hash;
}

得到哈希映射值

// 如果相同key值,则覆盖
int get_index(Hash* hash, Data data)
{assert(hash);int pos = data.key % hash->p;int curPos = pos;do {if (hash->data[curPos] == NULL || hash->data[curPos]->key == data.key) {return curPos;}curPos = (curPos + 1) % hash->p;} while (curPos != pos);return -1;   // 找不到,则当前满了,这里假设数据能够存储
}

插入数据

void push(Hash* hash, Data data)
{assert(hash);int pos = get_index(hash, data);if (pos == -1) {return;}if (hash->data[pos] == NULL) {Data* newData = (Data*)calloc(1, sizeof(Data));assert(newData);hash->data[pos] = newData;// 内存拷贝memcpy(hash->data[pos], &data, sizeof(data));}else {if (hash->data[pos]->key == data.key) {// 字符串拷贝strcpy(hash->data[pos]->buffer, data.buffer);}}hash->count++;
}

哈希查找

循环查找一圈看是否能找到。

Data* search(Hash* hash, int key)
{assert(hash);int pos = key % hash->count;int curPos = pos;do {if (hash->data[curPos] == NULL) {return NULL;}if (hash->data[curPos]->key == key) {return hash->data[curPos];}curPos = (curPos + 1) % hash->p;} while (pos != curPos);return NULL;
}

总代码

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>/*f(key) = key / p;
*/// 这里假设存储的数据是这个,key是自己抽象出来的
typedef struct Data {int key;char buffer[20];
}Data;typedef struct Hash {Data** data;int p;int count;
}Hash;Hash* create_hash(int p)
{Hash* hash = (Hash*)calloc(1, sizeof(Hash));assert(hash);hash->data = (Data**)calloc(p, sizeof(Data));assert(hash->data);hash->p = p;return hash;
}// 如果相同key值,则覆盖
int get_index(Hash* hash, Data data)
{assert(hash);int pos = data.key % hash->p;int curPos = pos;do {if (hash->data[curPos] == NULL || hash->data[curPos]->key == data.key) {return curPos;}curPos = (curPos + 1) % hash->p;} while (curPos != pos);return -1;   // 找不到,则当前满了,这里假设数据能够存储
}void push(Hash* hash, Data data)
{assert(hash);int pos = get_index(hash, data);if (pos == -1) {return;}if (hash->data[pos] == NULL) {Data* newData = (Data*)calloc(1, sizeof(Data));assert(newData);hash->data[pos] = newData;// 内存拷贝memcpy(hash->data[pos], &data, sizeof(data));}else {if (hash->data[pos]->key == data.key) {// 字符串拷贝strcpy(hash->data[pos]->buffer, data.buffer);}}hash->count++;
}void print_hash(Hash* hash)
{assert(hash);for (int i = 0; i < hash->p; i++) {if (hash->data[i] == NULL) {printf("NULL\n");}else {printf("%d %s\n", hash->data[i]->key, hash->data[i]->buffer);}}
}Data* search(Hash* hash, int key)
{assert(hash);int pos = key % hash->count;int curPos = pos;do {if (hash->data[curPos] == NULL) {return NULL;}if (hash->data[curPos]->key == key) {return hash->data[curPos];}curPos = (curPos + 1) % hash->p;} while (pos != curPos);return NULL;
}int size(Hash* hash)
{assert(hash);return hash->count;
}bool empty(Hash* hash)
{assert(hash);return hash->count == 0;
}int main()
{Hash* hash = create_hash(11);Data data[8] = { 1,"小美",11,"小芳",25,"花花",38,"coco",45,"小帅",88,"baby",65,"小丽",75,"小小" };for (int i = 0; i < 8; i++) {push(hash, data[i]);}print_hash(hash);Data* sdata = search(hash, 45);printf("search: %d %s\n", sdata->key, sdata->buffer);return 0;
}

链表哈希案例实现

封装

// 数据封装
typedef struct Data {int key;char buffer[20];
}Data;// 横向链表节点封装(解决冲突节点)
typedef struct LNode {Data data;struct LNode* next;
}LNode;// 纵向链表节点封装
typedef struct SNode {Data data;struct SNode* snext;LNode* lnext;    // 解决冲突链表
}SNode;// 哈希封装
typedef struct Hash {SNode* headNode;int p;   // 余数int count;   // 存储的元素个数
}Hash;LNode* create_lnode(Data data)
{LNode* node = (LNode*)calloc(1, sizeof(LNode));assert(node);node->data = data;return node;
}SNode* create_snode(Data data)
{SNode* node = (SNode*)calloc(1, sizeof(SNode));assert(node);node->data = data;return node;
}Hash* create_hash(int p)
{Hash* hash = (Hash*)calloc(1, sizeof(Hash));assert(hash);hash->p = p;return hash;
}

插入

这个确实规矩有点多,如:

  • 第一步得到哈希映射值
    • 如果在主链表中已经存在了,则在主链表映射位置拉一条链表,头插(这里是)
    • 如果主链表中不存在,则插入主链表中
// 插入
// 规则有点多
void push(Hash* hash, Data data)
{assert(hash);// 创建节点SNode* new_node = create_snode(data);int pos = data.key % hash->p;// 没有,则纵向链表生成if (hash->headNode == NULL) {hash->headNode = new_node;}else {   // 检查SNode* insert = hash->headNode;SNode* prevInsert = NULL;// if (insert->data.key % hash->p > pos) {new_node->snext = hash->headNode;hash->headNode = new_node;hash->count++;}else {while (insert != NULL && (insert->data.key % hash->p < pos)) {prevInsert = insert;insert = insert->snext;}// if (insert == NULL) {prevInsert->snext = new_node;hash->count++;}else if (insert->data.key % hash->p == pos) {//if (insert->data.key == data.key) {strcpy(insert->data.buffer, data.buffer);}else {LNode* curNode = insert->lnext;if (curNode == NULL) {insert->lnext = create_lnode(data);hash->count++;}else {// 横向插入,头插while (curNode != NULL && curNode->data.key != data.key) {curNode = curNode->next;}// 没有,头插if (curNode == NULL) {LNode* temp = create_lnode(data);temp->next = insert->lnext;insert->lnext = temp;hash->count++;}else {   // 有,覆盖strcpy(curNode->data.buffer, data.buffer);}}}}else {new_node->snext = insert;prevInsert->snext = new_node;hash->count++;}}}}

查找

这个查找分为两个步骤:

  1. 主链表中找(纵向)
  2. 在映射值的那个链表中找
// 打印
void print_hash(Hash* hash)
{assert(hash);SNode* rTemp = hash->headNode;while (rTemp) {printf("key: %d, value: %s", rTemp->data.key, rTemp->data.buffer);if (rTemp->lnext != NULL) {printf(" 【");LNode* lTemp = rTemp->lnext;while (lTemp != NULL) {printf("key: %d, value: %s", lTemp->data.key, lTemp->data.buffer);lTemp = lTemp->next;}printf("  】");//  看清楚这个是行的数据}rTemp = rTemp->snext;printf("\n");}}// 查找
enum MatchType
{NoMatch,  // 没有RowMatch,  // 纵找到ColMatch   // 横找到
};typedef struct Match {int type;union {LNode* lnode;SNode* snode;};
}Match;Match search(Hash* hash, Data data)
{assert(hash);Match res = { 0 };int pos = data.key % hash->p;SNode* rTemp = hash->headNode;while (rTemp) {if (pos == rTemp->data.key % hash->p) {if (data.key == rTemp->data.key) {res.type = RowMatch;res.snode = rTemp;return res;}else {LNode* lTemp = rTemp->lnext;while (lTemp) {if (lTemp->data.key == data.key) {res.type = ColMatch;res.lnode = lTemp;return res;}lTemp == lTemp->next;}}}rTemp = rTemp->snext;}return res;
}void print_search(Match match)
{switch (match.type){case NoMatch:printf("没有找到\n");break;case RowMatch:printf("找到了,key: %d, value: %s\n", match.snode->data.key, match.snode->data.buffer);break;case ColMatch:printf("找到了,key: %d, value: %s\n", match.lnode->data.key, match.lnode->data.buffer);break;}
}

总代码

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <string.h>// 链表实现哈希,使用链表法解决冲突,要注意的是封装会比较多
// 假设不处理重复值// 数据封装
typedef struct Data {int key;char buffer[20];
}Data;// 横向链表节点封装(解决冲突节点)
typedef struct LNode {Data data;struct LNode* next;
}LNode;// 纵向链表节点封装
typedef struct SNode {Data data;struct SNode* snext;LNode* lnext;    // 解决冲突链表
}SNode;// 哈希封装
typedef struct Hash {SNode* headNode;int p;   // 余数int count;   // 存储的元素个数
}Hash;LNode* create_lnode(Data data)
{LNode* node = (LNode*)calloc(1, sizeof(LNode));assert(node);node->data = data;return node;
}SNode* create_snode(Data data)
{SNode* node = (SNode*)calloc(1, sizeof(SNode));assert(node);node->data = data;return node;
}Hash* create_hash(int p)
{Hash* hash = (Hash*)calloc(1, sizeof(Hash));assert(hash);hash->p = p;return hash;
}// 插入
// 规则有点多
void push(Hash* hash, Data data)
{assert(hash);// 创建节点SNode* new_node = create_snode(data);int pos = data.key % hash->p;// 没有,则纵向链表生成if (hash->headNode == NULL) {hash->headNode = new_node;}else {   // 检查SNode* insert = hash->headNode;SNode* prevInsert = NULL;// if (insert->data.key % hash->p > pos) {new_node->snext = hash->headNode;hash->headNode = new_node;hash->count++;}else {while (insert != NULL && (insert->data.key % hash->p < pos)) {prevInsert = insert;insert = insert->snext;}// if (insert == NULL) {prevInsert->snext = new_node;hash->count++;}else if (insert->data.key % hash->p == pos) {//if (insert->data.key == data.key) {strcpy(insert->data.buffer, data.buffer);}else {LNode* curNode = insert->lnext;if (curNode == NULL) {insert->lnext = create_lnode(data);hash->count++;}else {// 横向插入,头插while (curNode != NULL && curNode->data.key != data.key) {curNode = curNode->next;}// 没有,头插if (curNode == NULL) {LNode* temp = create_lnode(data);temp->next = insert->lnext;insert->lnext = temp;hash->count++;}else {   // 有,覆盖strcpy(curNode->data.buffer, data.buffer);}}}}else {new_node->snext = insert;prevInsert->snext = new_node;hash->count++;}}}}// 打印
void print_hash(Hash* hash)
{assert(hash);SNode* rTemp = hash->headNode;while (rTemp) {printf("key: %d, value: %s", rTemp->data.key, rTemp->data.buffer);if (rTemp->lnext != NULL) {printf(" 【");LNode* lTemp = rTemp->lnext;while (lTemp != NULL) {printf("key: %d, value: %s", lTemp->data.key, lTemp->data.buffer);lTemp = lTemp->next;}printf("  】");//  看清楚这个是行的数据}rTemp = rTemp->snext;printf("\n");}}// 查找
enum MatchType
{NoMatch,  // 没有RowMatch,  // 纵找到ColMatch   // 横找到
};typedef struct Match {int type;union {LNode* lnode;SNode* snode;};
}Match;Match search(Hash* hash, Data data)
{assert(hash);Match res = { 0 };int pos = data.key % hash->p;SNode* rTemp = hash->headNode;while (rTemp) {if (pos == rTemp->data.key % hash->p) {if (data.key == rTemp->data.key) {res.type = RowMatch;res.snode = rTemp;return res;}else {LNode* lTemp = rTemp->lnext;while (lTemp) {if (lTemp->data.key == data.key) {res.type = ColMatch;res.lnode = lTemp;return res;}lTemp == lTemp->next;}}}rTemp = rTemp->snext;}return res;
}void print_search(Match match)
{switch (match.type){case NoMatch:printf("没有找到\n");break;case RowMatch:printf("找到了,key: %d, value: %s\n", match.snode->data.key, match.snode->data.buffer);break;case ColMatch:printf("找到了,key: %d, value: %s\n", match.lnode->data.key, match.lnode->data.buffer);break;}
}int main()
{Hash* hash = create_hash(11);Data data[8] = { 1,"小美",11,"小芳",25,"花花",38,"coco",42,"小帅",88,"baby",66,"小丽",77,"小小" };for (int i = 0; i < 8; i++) {push(hash, data[i]);}print_hash(hash);printf("********************\n");Match search_res = search(hash, data[3]);print_search(search_res);return 0;
}

相关文章:

数据结构C语言描述8(图文结合)--哈希、哈希冲突、开放地址法、链地址法等实现

前言 这个专栏将会用纯C实现常用的数据结构和简单的算法&#xff1b;有C基础即可跟着学习&#xff0c;代码均可运行&#xff1b;准备考研的也可跟着写&#xff0c;个人感觉&#xff0c;如果时间充裕&#xff0c;手写一遍比看书、刷题管用很多&#xff0c;这也是本人采用纯C语言…...

自动化立体库安全使用管理制度完整版

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。欢迎大家到本文底部评论区留言。 新书《智能物流系统构成与技术实践》人俱乐部 完整版文件和更多学习资料&#xff0c;请球友到知识星球【智能仓储物流技术研习社】自行下载。 以下是《…...

云打印之拼多多打印组件交互协议

拼多多打印组件交互协议相关介绍如下&#xff1a; 1、打印组件下载地址 http://meta.pinduoduo.com/api/one/app/v1/lateststable?appIdcom.xunmeng.pddprint&platformwindows&subTypemain 2、socket连接端口 如果是http的话&#xff0c;端口是5000 socket new …...

TCP 演进之路:软硬件跷跷板与新征程

今天依旧是与 TCP 相关的一个短评。 先看软硬件间的胶着。晶体管诞生以来&#xff0c;硬件一直在突飞猛进发展&#xff0c;后来这个事被摩尔定律正则化&#xff0c;人们开始可以预测未来&#xff0c;但即便如此&#xff0c;软件依然跟不上来&#xff0c;不过几年&#xff0c;老…...

React最小状态管理Jotai

Jotai 状态管理 1. 简介 Jotai 是一个基于原子 atom 概念的 React 状态管理库&#xff0c;它提供了简单且灵活的方式来管理应用状态, 而且非常轻量&#xff0c; 大厂用的非常多。 JotaiRedux适合单个页面&#xff0c;多次用到的属性适合全局公共属性超级轻量&#xff08;与use…...

计算机网络 —— 网络编程(TCP)

计算机网络 —— 网络编程&#xff08;TCP&#xff09; TCP和UDP的区别TCP (Transmission Control Protocol)UDP (User Datagram Protocol) 前期准备listen &#xff08;服务端&#xff09;函数原型返回值使用示例注意事项 accpect &#xff08;服务端&#xff09;函数原型返回…...

字玩FontPlayer开发笔记4 性能优化 首屏加载时间优化

字玩FontPlayer开发笔记4 性能优化 首屏加载时间优化 字玩FontPlayer是笔者开源的一款字体设计工具&#xff0c;使用Vue3 ElementUI开发&#xff0c;源代码&#xff1a; github: https://github.com/HiToysMaker/fontplayer gitee: https://gitee.com/toysmaker/fontplayer …...

RabbitMQ案例

1. 导入依赖 <!--AMQP依赖&#xff0c;包含RabbitMQ--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency> 发送消息 注入RabbitTemplate Autowired RabbitT…...

智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之13 方案再探之4:特定于领域的模板 之 div模型(完整版)

前景提要 整个“方案再探”篇 围绕着如何将项目附件文档中Part 1 部分中给出的零散问题讨论整理、重组为一个结构化的设计文档。为此提出了讨论题目&#xff1a; 特定于领域的模板--一个三套接的hoc结构 它是本项目actors 的剧本原型。其地位&#xff1a; 祖传代码脚本模板…...

WebRtc02:WebRtc架构、目录结构、运行机制

整体架构 WebRtc主要分为三层&#xff1a; CAPI层&#xff1a;外层调用Session管理核心层&#xff1a;包括视频引擎、音频引擎、网络传输 可由使用者重写视频引擎&#xff1a;编解码器、视频缓存、视频增强音频引擎&#xff1a;编解码器、音频缓存、回音消除、降噪传输&#x…...

数据结构复习 (顺序查找,对半查找,斐波那契查找,插值查找,分块查找)

查找&#xff08;检索&#xff09;&#xff1a; 定义&#xff1a;从给定的数据中找到对应的K 1&#xff0c;顺序查找&#xff1a; O(n)的从前向后的遍历 2&#xff0c;对半查找&#xff0c;要求有序 从中间开始查找&#xff0c;每次检查中间的是否正确&#xff0c;不正确就…...

el-input输入框需要支持多输入,最后传输给后台的字段值以逗号分割

需求&#xff1a;一个输入框字段需要支持多次输入&#xff0c;最后传输给后台的字段值以逗号分割 解决方案&#xff1a;结合了el-tag组件的动态编辑标签 那块的代码 //子组件 <template><div class"input-multiple-box" idinputMultipleBox><div>…...

C# 枚举格式字符串

总目录 前言 当前文章为 C# 中的格式设置(格式化字符串) 大全 中的一个小章节。 一、概述 1. 基本信息 可以使用 Enum.ToString 方法&#xff0c;新建表示枚举成员的数字值、十六进制值或字符串值的字符串对象。枚举格式说明符不区分大小写。 二、自定义数字格式说明符详解…...

【51单片机-零基础chapter1】

安装软件(配套的有,不多赘述) 1.管理员身份运行keil和破解软件kegen 将CID代码复制粘贴到 一定要管理员方式,不然会error 插入板子 我的电脑,管理 1.如果是拯救者,查看端口,如果没有则显示隐藏 2.苹果不知道,好像不可以 3.其他电脑在"其他设备找" (注:本人在校已…...

记录:导出功能:接收文件流数据进行导出(vue3)

请求接口&#xff1a;一定要加responseType: blob 后端返回数据&#xff1a; api.js export function export() {return request({url: dev/api/export,method: get,responseType: blob,//一定要加}) } vue&#xff1a; import {export} from /api// 导出 const exportTab…...

基于Spring Boot + Vue3实现的在线汽车保养维修预约管理系统源码+文档

前言 基于Spring Boot Vue3实现的在线汽车保养维修预约管理系统是一种前后端分离架构的应用&#xff0c;它结合了Java后端开发框架Spring Boot和现代JavaScript前端框架Vue.js 3.0的优势。这样的系统可以为汽车服务站提供一个高效的平台来管理客户的预约请求 技术选型 系统…...

PHP框架+gatewayworker实现在线1对1聊天--接收消息(7)

文章目录 接收消息的原理接收消息JavaScript代码 接收消息的原理 接收消息&#xff0c;就是接受服务器转发的客户端消息。并不需要单独创建函数&#xff0c;因为 ws.onmessage会自动接收消息。我们需要在这个函数里进行处理。因为初始化的时候&#xff0c;已经处理的init类型的…...

18.1、网络安全策略分类 流程 内容

目录 网络安全测评概况网络安全测评类型—基于测评目标分类网络安全测评类型—基于实施方式分类网络安全测评类型—基于测评对象保密性分类网络安全等级保护测评内容网络安全测评流程与内容 网络安全测评概况 网络安全测评&#xff0c;它是指参照一定的标准规范要求&#xff0…...

深入理解连接池:从数据库到HTTP的优化之道

在现代应用开发中&#xff0c;高效的资源管理是关键&#xff0c;其中连接池&#xff08;Connection Pool&#xff09;技术起到了至关重要的作用。本文将带你深入了解连接池的概念及其在数据库和HTTP通信中的应用&#xff0c;结合 JDBC 与 Druid 的关系&#xff0c;以及 HttpURL…...

【2025最新计算机毕业设计】基于SpringBoot+Vue智慧养老医护系统(高质量源码,提供文档,免费部署到本地)【提供源码+答辩PPT+文档+项目部署】

作者简介&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容&#xff1a;&#x1f31f;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用&#xff0c;用户可以通过网页界面上传黑白视频&#xff0c;系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观&#xff0c;不需要了解技术细节。 效果图 ​二、实现思路 总体思路&#xff1a; 用户通过Gradio界面上…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...