C 语言中的高级数据结构与内存管理
一、引言
C 语言作为一种广泛应用的系统级编程语言,以其高效性和灵活性著称。在 C 语言编程中,高级数据结构和内存管理是两个至关重要的方面。高级数据结构能够帮助我们更高效地组织和处理数据,而合理的内存管理则是保证程序性能和稳定性的关键。本文将深入探讨 C 语言中的高级数据结构和内存管理,结合丰富的代码示例和高级知识点,为读者提供全面而深入的理解。
二、高级数据结构
2.1 图(Graph)
2.1.1 图的基本概念
图是一种由节点(顶点)和连接这些节点的边组成的数据结构。图可以用来表示各种实际问题,如社交网络、交通网络等。图分为有向图和无向图,有向图的边有方向,而无向图的边没有方向。此外,图还可以分为加权图和无权图,加权图的边带有权重,而无权图的边没有权重。
2.1.2 图的表示方法
在 C 语言中,常用的图的表示方法有邻接矩阵和邻接表。
邻接矩阵
邻接矩阵是一个二维数组,其中 matrix[i][j]
表示顶点 i
到顶点 j
是否有边相连。如果是无权图,matrix[i][j]
可以用 0 或 1 表示;如果是加权图,matrix[i][j]
可以用边的权重表示。
#include <stdio.h>
#define MAX_VERTICES 100// 邻接矩阵表示图
typedef struct {int vertices;int matrix[MAX_VERTICES][MAX_VERTICES];
} Graph;// 初始化图
void initGraph(Graph *g, int v) {g->vertices = v;for (int i = 0; i < v; i++) {for (int j = 0; j < v; j++) {g->matrix[i][j] = 0;}}
}// 添加边
void addEdge(Graph *g, int src, int dest) {g->matrix[src][dest] = 1;// 如果是无向图,还需要添加反向边g->matrix[dest][src] = 1;
}// 打印图
void printGraph(Graph *g) {for (int i = 0; i < g->vertices; i++) {for (int j = 0; j < g->vertices; j++) {printf("%d ", g->matrix[i][j]);}printf("\n");}
}int main() {Graph g;int vertices = 5;initGraph(&g, vertices);addEdge(&g, 0, 1);addEdge(&g, 0, 4);addEdge(&g, 1, 2);addEdge(&g, 1, 3);addEdge(&g, 1, 4);addEdge(&g, 2, 3);addEdge(&g, 3, 4);printGraph(&g);return 0;
}
邻接表
邻接表是一种链表数组,每个数组元素对应一个顶点,链表中存储与该顶点相邻的顶点。
#include <stdio.h>
#include <stdlib.h>// 邻接表节点
typedef struct AdjListNode {int dest;struct AdjListNode* next;
} AdjListNode;// 邻接表头节点
typedef struct AdjList {AdjListNode *head;
} AdjList;// 图
typedef struct {int vertices;AdjList* array;
} Graph;// 创建新的邻接表节点
AdjListNode* newAdjListNode(int dest) {AdjListNode* newNode = (AdjListNode*)malloc(sizeof(AdjListNode));newNode->dest = dest;newNode->next = NULL;return newNode;
}// 创建图
Graph* createGraph(int vertices) {Graph* graph = (Graph*)malloc(sizeof(Graph));graph->vertices = vertices;graph->array = (AdjList*)malloc(vertices * sizeof(AdjList));for (int i = 0; i < vertices; i++) {graph->array[i].head = NULL;}return graph;
}// 添加边
void addEdge(Graph* graph, int src, int dest) {AdjListNode* newNode = newAdjListNode(dest);newNode->next = graph->array[src].head;graph->array[src].head = newNode;// 如果是无向图,添加反向边newNode = newAdjListNode(src);newNode->next = graph->array[dest].head;graph->array[dest].head = newNode;
}// 打印图
void printGraph(Graph* graph) {for (int i = 0; i < graph->vertices; i++) {AdjListNode* pCrawl = graph->array[i].head;printf("\n Adjacency list of vertex %d\n head ", i);while (pCrawl) {printf("-> %d", pCrawl->dest);pCrawl = pCrawl->next;}printf("\n");}
}int main() {int vertices = 5;Graph* graph = createGraph(vertices);addEdge(graph, 0, 1);addEdge(graph, 0, 4);addEdge(graph, 1, 2);addEdge(graph, 1, 3);addEdge(graph, 1, 4);addEdge(graph, 2, 3);addEdge(graph, 3, 4);printGraph(graph);return 0;
}
2.1.3 图的遍历算法
图的遍历算法主要有深度优先搜索(DFS)和广度优先搜索(BFS)。
深度优先搜索(DFS)
深度优先搜索是一种递归的遍历算法,它从一个顶点开始,沿着一条路径尽可能深地访问顶点,直到无法继续,然后回溯到上一个顶点,继续探索其他路径。
#include <stdio.h>
#include <stdlib.h>// 邻接表节点
typedef struct AdjListNode {int dest;struct AdjListNode* next;
} AdjListNode;// 邻接表头节点
typedef struct AdjList {AdjListNode *head;
} AdjList;// 图
typedef struct {int vertices;AdjList* array;
} Graph;// 创建新的邻接表节点
AdjListNode* newAdjListNode(int dest) {AdjListNode* newNode = (AdjListNode*)malloc(sizeof(AdjListNode));newNode->dest = dest;newNode->next = NULL;return newNode;
}// 创建图
Graph* createGraph(int vertices) {Graph* graph = (Graph*)malloc(sizeof(Graph));graph->vertices = vertices;graph->array = (AdjList*)malloc(vertices * sizeof(AdjList));for (int i = 0; i < vertices; i++) {graph->array[i].head = NULL;}return graph;
}// 添加边
void addEdge(Graph* graph, int src, int dest) {AdjListNode* newNode = newAdjListNode(dest);newNode->next = graph->array[src].head;graph->array[src].head = newNode;// 如果是无向图,添加反向边newNode = newAdjListNode(src);newNode->next = graph->array[dest].head;graph->array[dest].head = newNode;
}// 深度优先搜索辅助函数
void DFSUtil(Graph* graph, int v, int visited[]) {visited[v] = 1;printf("%d ", v);AdjListNode* pCrawl = graph->array[v].head;while (pCrawl) {int adjVertex = pCrawl->dest;if (!visited[adjVertex]) {DFSUtil(graph, adjVertex, visited);}pCrawl = pCrawl->next;}
}// 深度优先搜索
void DFS(Graph* graph, int startVertex) {int* visited = (int*)calloc(graph->vertices, sizeof(int));DFSUtil(graph, startVertex, visited);free(visited);
}int main() {int vertices = 5;Graph* graph = createGraph(vertices);addEdge(graph, 0, 1);addEdge(graph, 0, 4);addEdge(graph, 1, 2);addEdge(graph, 1, 3);addEdge(graph, 1, 4);addEdge(graph, 2, 3);addEdge(graph, 3, 4);printf("深度优先搜索从顶点 0 开始:\n");DFS(graph, 0);return 0;
}
广度优先搜索(BFS)
广度优先搜索是一种基于队列的遍历算法,它从一个顶点开始,逐层地访问相邻的顶点。
#include <stdio.h>
#include <stdlib.h>// 邻接表节点
typedef struct AdjListNode {int dest;struct AdjListNode* next;
} AdjListNode;// 邻接表头节点
typedef struct AdjList {AdjListNode *head;
} AdjList;// 图
typedef struct {int vertices;AdjList* array;
} Graph;// 创建新的邻接表节点
AdjListNode* newAdjListNode(int dest) {AdjListNode* newNode = (AdjListNode*)malloc(sizeof(AdjListNode));newNode->dest = dest;newNode->next = NULL;return newNode;
}// 创建图
Graph* createGraph(int vertices) {Graph* graph = (Graph*)malloc(sizeof(Graph));graph->vertices = vertices;graph->array = (AdjList*)malloc(vertices * sizeof(AdjList));for (int i = 0; i < vertices; i++) {graph->array[i].head = NULL;}return graph;
}// 添加边
void addEdge(Graph* graph, int src, int dest) {AdjListNode* newNode = newAdjListNode(dest);newNode->next = graph->array[src].head;graph->array[src].head = newNode;// 如果是无向图,添加反向边newNode = newAdjListNode(src);newNode->next = graph->array[dest].head;graph->array[dest].head = newNode;
}// 广度优先搜索
void BFS(Graph* graph, int startVertex) {int* visited = (int*)calloc(graph->vertices, sizeof(int));int* queue = (int*)malloc(graph->vertices * sizeof(int));int front = 0, rear = 0;visited[startVertex] = 1;queue[rear++] = startVertex;while (front < rear) {int currentVertex = queue[front++];printf("%d ", currentVertex);AdjListNode* pCrawl = graph->array[currentVertex].head;while (pCrawl) {int adjVertex = pCrawl->dest;if (!visited[adjVertex]) {visited[adjVertex] = 1;queue[rear++] = adjVertex;}pCrawl = pCrawl->next;}}free(visited);free(queue);
}int main() {int vertices = 5;Graph* graph = createGraph(vertices);addEdge(graph, 0, 1);addEdge(graph, 0, 4);addEdge(graph, 1, 2);addEdge(graph, 1, 3);addEdge(graph, 1, 4);addEdge(graph, 2, 3);addEdge(graph, 3, 4);printf("广度优先搜索从顶点 0 开始:\n");BFS(graph, 0);return 0;
}
2.2 堆(Heap)
2.2.1 堆的基本概念
堆是一种特殊的树形数据结构,它通常是一个完全二叉树。堆分为最大堆和最小堆,最大堆的每个节点的值都大于或等于其子节点的值,最小堆的每个节点的值都小于或等于其子节点的值。
2.2.2 堆的实现
在 C 语言中,可以使用数组来实现堆。
#include <stdio.h>
#include <stdlib.h>// 交换两个元素
void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}// 最大堆化
void maxHeapify(int arr[], int n, int i) {int largest = i;int left = 2 * i + 1;int right = 2 * i + 2;if (left < n && arr[left] > arr[largest]) {largest = left;}if (right < n && arr[right] > arr[largest]) {largest = right;}if (largest != i) {swap(&arr[i], &arr[largest]);maxHeapify(arr, n, largest);}
}// 构建最大堆
void buildMaxHeap(int arr[], int n) {for (int i = n / 2 - 1; i >= 0; i--) {maxHeapify(arr, n, i);}
}// 堆排序
void heapSort(int arr[], int n) {buildMaxHeap(arr, n);for (int i = n - 1; i > 0; i--) {swap(&arr[0], &arr[i]);maxHeapify(arr, i, 0);}
}// 打印数组
void printArray(int arr[], int n) {for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");
}int main() {int arr[] = {12, 11, 13, 5, 6, 7};int n = sizeof(arr) / sizeof(arr[0]);printf("排序前的数组:\n");printArray(arr, n);heapSort(arr, n);printf("排序后的数组:\n");printArray(arr, n);return 0;
}
2.2.3 堆的应用
堆的常见应用包括堆排序、优先队列等。优先队列是一种特殊的队列,它的元素按照优先级进行排序,优先级高的元素先出队。可以使用堆来实现优先队列。
#include <stdio.h>
#include <stdlib.h>// 交换两个元素
void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}// 最小堆化
void minHeapify(int arr[], int n, int i) {int smallest = i;int left = 2 * i + 1;int right = 2 * i + 2;if (left < n && arr[left] < arr[smallest]) {smallest = left;}if (right < n && arr[right] < arr[smallest]) {smallest = right;}if (smallest != i) {swap(&arr[i], &arr[smallest]);minHeapify(arr, n, smallest);}
}// 插入元素到最小堆
void insertMinHeap(int arr[], int *n, int key) {(*n)++;int i = *n - 1;arr[i] = key;while (i > 0 && arr[(i - 1) / 2] > arr[i]) {swap(&arr[i], &arr[(i - 1) / 2]);i = (i - 1) / 2;}
}// 从最小堆中提取最小元素
int extractMin(int arr[], int *n) {if (*n <= 0) {return -1;}if (*n == 1) {(*n)--;return arr[0];}int root = arr[0];arr[0] = arr[*n - 1];(*n)--;minHeapify(arr, *n, 0);return root;
}int main() {int arr[100];int n = 0;insertMinHeap(arr, &n, 3);insertMinHeap(arr, &n, 2);insertMinHeap(arr, &n, 15);insertMinHeap(arr, &n, 5);insertMinHeap(arr, &n, 4);insertMinHeap(arr, &n, 45);printf("最小元素:%d\n", extractMin(arr, &n));printf("最小元素:%d\n", extractMin(arr, &n));return 0;
}
三、内存管理
3.1 动态内存分配
在 C 语言中,动态内存分配允许程序在运行时分配和释放内存。常用的动态内存分配函数有 malloc
、calloc
、realloc
和 free
。
3.1.1 malloc 函数
malloc
函数用于分配指定大小的内存块,返回一个指向该内存块的指针。
#include <stdio.h>
#include <stdlib.h>int main() {int n = 5;int *arr = (int*)malloc(n * sizeof(int));if (arr == NULL) {printf("内存分配失败\n");return 1;}for (int i = 0; i < n; i++) {arr[i] = i + 1;}for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");free(arr);return 0;
}
3.1.2 calloc 函数
calloc
函数用于分配指定数量和大小的内存块,并将其初始化为 0。
#include <stdio.h>
#include <stdlib.h>int main() {int n = 5;int *arr = (int*)calloc(n, sizeof(int));if (arr == NULL) {printf("内存分配失败\n");return 1;}for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");free(arr);return 0;
}
3.1.3 realloc 函数
realloc
函数用于调整已分配内存块的大小。
#include <stdio.h>
#include <stdlib.h>int main() {int n = 5;int *arr = (int*)malloc(n * sizeof(int));if (arr == NULL) {printf("内存分配失败\n");return 1;}for (int i = 0; i < n; i++) {arr[i] = i + 1;}int newSize = 10;arr = (int*)realloc(arr, newSize * sizeof(int));if (arr == NULL) {printf("内存重新分配失败\n");return 1;}for (int i = n; i < newSize; i++) {arr[i] = i + 1;}for (int i = 0; i < newSize; i++) {printf("%d ", arr[i]);}printf("\n");free(arr);return 0;
}
3.1.4 free 函数
free
函数用于释放之前分配的内存块。
#include <stdio.h>
#include <stdlib.h>int main() {int *ptr = (int*)malloc(sizeof(int));if (ptr == NULL) {printf("内存分配失败\n");return 1;}*ptr = 10;printf("分配的内存中存储的值:%d\n", *ptr);free(ptr);return 0;
}
3.2 内存泄漏与避免
内存泄漏是指程序在运行过程中分配了内存,但在不再使用时没有释放,导致可用内存不断减少。为了避免内存泄漏,需要遵循以下原则:
- 确保每次调用
malloc
、calloc
或realloc
后,都有对应的free
调用。 - 在函数返回之前,释放函数内部分配的动态内存。
- 避免在循环中不断分配内存而不释放。
#include <stdio.h>
#include <stdlib.h>// 错误示例:存在内存泄漏
void memoryLeakExample() {int *ptr = (int*)malloc(sizeof(int));// 没有释放内存
}// 正确示例:避免内存泄漏
void noMemoryLeakExample() {int *ptr = (int*)malloc(sizeof(int));if (ptr != NULL) {*ptr = 10;free(ptr);}
}int main() {memoryLeakExample();noMemoryLeakExample();return 0;
}
3.3 内存对齐
内存对齐是指数据在内存中的存储方式,它要求数据的起始地址必须是其大小的整数倍。内存对齐可以提高内存访问效率,但会增加内存的使用量。
#include <stdio.h>// 未对齐的结构体
struct UnalignedStruct {char c;int i;short s;
};// 对齐的结构体
#pragma pack(1)
struct AlignedStruct {char c;int i;short s;
};
#pragma pack()int main() {printf("未对齐结构体的大小:%zu\n", sizeof(struct UnalignedStruct));printf("对齐结构体的大小:%zu\n", sizeof(struct AlignedStruct));return 0;
}
3.4 内存池技术
内存池技术是一种优化内存分配和释放的技术,它预先分配一块较大的内存块,然后在需要时从这块内存块中分配小块内存,避免了频繁的系统调用,提高了内存分配和释放的效率。
#include <stdio.h>
#include <stdlib.h>#define BLOCK_SIZE 1024
#define POOL_SIZE 10// 内存块
typedef struct MemoryBlock {struct MemoryBlock *next;char data[BLOCK_SIZE];
} MemoryBlock;// 内存池
typedef struct MemoryPool {MemoryBlock *head;int count;
} MemoryPool;// 初始化内存池
void initMemoryPool(MemoryPool *pool) {pool->head = NULL;pool->count = 0;for (int i = 0; i < POOL_SIZE; i++) {MemoryBlock *block = (MemoryBlock*)malloc(sizeof(MemoryBlock));block->next = pool->head;pool->head = block;pool->count++;}
}// 从内存池分配内存
void* allocateFromPool(MemoryPool *pool) {if (pool->head == NULL) {return NULL;}MemoryBlock *block = pool->head;pool->head = block->next;pool->count--;return (void*)block->data;
}// 将内存块返回给内存池
void freeToPool(MemoryPool *pool, void *ptr) {MemoryBlock *block = (MemoryBlock*)((char*)ptr - offsetof(MemoryBlock, data));block->next = pool->head;pool->head = block;pool->count++;
}// 销毁内存池
void destroyMemoryPool(MemoryPool *pool) {MemoryBlock *current = pool->head;while (current != NULL) {MemoryBlock *next = current->next;free(current);current = next;}pool->head = NULL;pool->count = 0;
}int main() {MemoryPool pool;initMemoryPool(&pool);void *ptr1 = allocateFromPool(&pool);void *ptr2 = allocateFromPool(&pool);if (ptr1 != NULL) {printf("从内存池分配的内存地址:%p\n", ptr1);}if (ptr2 != NULL) {printf("从内存池分配的内存地址:%p\n", ptr2);}freeToPool(&pool, ptr1);freeToPool(&pool, ptr2);destroyMemoryPool(&pool);return 0;
}
四、高级数据结构与内存管理的结合应用
4.1 图的内存管理
在实现图的过程中,需要合理管理内存。例如,在使用邻接表表示图时,每个顶点的邻接表节点都需要动态分配内存,在不再使用图时,需要释放这些内存。
#include <stdio.h>
#include <stdlib.h>// 邻接表节点
typedef struct AdjListNode {int dest;struct AdjListNode* next;
} AdjListNode;// 邻接表头节点
typedef struct AdjList {AdjListNode *head;
} AdjList;// 图
typedef struct {int vertices;AdjList* array;
} Graph;// 创建新的邻接表节点
AdjListNode* newAdjListNode(int dest) {AdjListNode* newNode = (AdjListNode*)malloc(sizeof(AdjListNode));newNode->dest = dest;newNode->next = NULL;return newNode;
}// 创建图
Graph* createGraph(int vertices) {Graph* graph = (Graph*)malloc(sizeof(Graph));graph->vertices = vertices;graph->array = (AdjList*)malloc(vertices * sizeof(AdjList));for (int i = 0; i < vertices; i++) {graph->array[i].head = NULL;}return graph;
}// 添加边
void addEdge(Graph* graph, int src, int dest) {AdjListNode* newNode = newAdjListNode(dest);newNode->next = graph->array[src].head;graph->array[src].head = newNode;// 如果是无向图,添加反向边newNode = newAdjListNode(src);newNode->next = graph->array[dest].head;graph->array[dest].head = newNode;
}// 释放图的内存
void freeGraph(Graph* graph) {for (int i = 0; i < graph->vertices; i++) {AdjListNode* current = graph->array[i].head;while (current != NULL) {AdjListNode* next = current->next;free(current);current = next;}}free(graph->array);free(graph);
}int main() {int vertices = 5;Graph* graph = createGraph(vertices);addEdge(graph, 0, 1);addEdge(graph, 0, 4);addEdge(graph, 1, 2);addEdge(graph, 1, 3);addEdge(graph, 1, 4);addEdge(graph, 2, 3);addEdge(graph, 3, 4);// 使用图...freeGraph(graph);return 0;
}
4.2 堆的内存管理
在实现堆的过程中,同样需要注意内存的分配和释放。例如,在使用数组实现堆时,需要确保数组的内存分配和释放正确。
#include <stdio.h>
#include <stdlib.h>// 交换两个元素
void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}// 最大堆化
void maxHeapify(int arr[], int n, int i) {int largest = i;int left = 2 * i + 1;int right = 2 * i + 2;if (left < n && arr[left] > arr[largest]) {largest = left;}if (right < n && arr[right] > arr[largest]) {largest = right;}if (largest != i) {swap(&arr[i], &arr[largest]);maxHeapify(arr, n, largest);}
}// 构建最大堆
void buildMaxHeap(int arr[], int n) {for (int i = n / 2 - 1; i >= 0; i--) {maxHeapify(arr, n, i);}
}// 堆排序
void heapSort(int arr[], int n) {buildMaxHeap(arr, n);for (int i = n - 1; i > 0; i--) {swap(&arr[0], &arr[i]);maxHeapify(arr, i, 0);}
}int main() {int n = 5;int *arr = (int*)malloc(n * sizeof(int));if (arr == NULL) {printf("内存分配失败\n");return 1;}for (int i = 0; i < n; i++) {arr[i] = n - i;}heapSort(arr, n);for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");free(arr);return 0;
}
五、总结
本文深入探讨了 C 语言中的高级数据结构和内存管理。高级数据结构如 图和堆,为我们解决复杂的问题提供了强大的工具。图可以用于表示各种关系,通过不同的遍历算法可以对图进行有效的操作;堆则在排序和优先队列等方面有重要应用。
内存管理是 C 语言编程中不可忽视的部分,动态内存分配函数如 malloc
、calloc
、realloc
和 free
为我们提供了灵活的内存使用方式。但同时,我们需要注意避免内存泄漏,合理进行内存对齐,并可以采用内存池技术优化内存分配和释放的效率。
相关文章:
C 语言中的高级数据结构与内存管理
一、引言 C 语言作为一种广泛应用的系统级编程语言,以其高效性和灵活性著称。在 C 语言编程中,高级数据结构和内存管理是两个至关重要的方面。高级数据结构能够帮助我们更高效地组织和处理数据,而合理的内存管理则是保证程序性能和稳定性的关…...
Django 实现服务器主动给客户端发送消息的几种常见方式及其区别
Django Channels 原理 :Django Channels 是 Django 的一个扩展,它通过使用 WebSockets 等协议来处理长连接,使服务器能够与客户端建立持久连接,从而实现双向通信。一旦连接建立,服务器可以随时主动向客户端发送消息。…...
BR_频谱20dB 带宽(RF/TRM/CA/BV-05-C [TX Output Spectrum – 20 dB Bandwidth])
目录 一、规范要求 1、协议章节 2、测试目的 二、测试方法 1、样机初值条件: 2、测试步骤: 方法一:频谱仪 方法二:综测仪CMW500 3、预期结果 一、规范要求 1、协议章节 4.5.5 RF/TRM/CA/BV-05-C [TX Output Spectrum – 20 dB Ba…...
rabbitmq 面试题
一、基础概念 1. 什么是 RabbitMQ? - 基于 AMQP 协议的开源消息中间件,用于实现系统间的异步通信和解耦,支持多种消息模式(如发布/订阅、路由、主题等)。 1. 你了解那个rabbitmq, rabbitmq 的 虚拟机是…...
论文阅读:2025 arxiv AI Alignment: A Comprehensive Survey
总目录 大模型安全相关研究:https://blog.csdn.net/WhiffeYF/article/details/142132328 AI Alignment: A Comprehensive Survey https://arxiv.org/pdf/2310.19852 https://alignmentsurvey.com/ https://www.doubao.com/chat/3367091682540290 速览 研究动机…...
spring事务事务传播
POROPAGATION_REQUIRED(必须) 解释: 存在事务时 当前方法已在事务中运行,直接加入该事务 无事务 则自动开启一个新事物,并在方法执行结束后提交或者回滚 举例 java Transactional public void transfer() {accountService.reduceBalance…...
JMeter介绍
文章目录 1. JMeter简介2. JMeter 下载3. JMeter修改编码集4. 启动并运行JMeter 1. JMeter简介 JMeter 是 Apache 组织使用 Java 开发的一款测试工具: 1、可以用于对服务器、网络或对象模拟巨大的负载 2、通过创建带有断言的脚本来验证程序是否能返回期望的结果 优…...
Elasticsearch:使用 ES|QL 进行搜索和过滤
本教程展示了 ES|QL 语法的示例。请参考 Query DSL 版本,以获得等效的 Query DSL 语法示例。 这是一个使用 ES|QL 进行全文搜索和语义搜索基础知识的实践介绍。 有关 ES|QL 中所有搜索功能的概述,请参考《使用 ES|QL 进行搜索》。 在这个场景中&#x…...
面向新一代扩展现实(XR)应用的物联网框架
中文标题: 面向新一代扩展现实(XR)应用的物联网框架 英文标题: Towards an IoT Framework for the New Generation of XR Applications 作者信息 Joo A. Dias,UNIDCOM - IADE,欧洲大学,里斯本&…...
Docker Overlay 网络的核心工作(以跨节点容器通信为例)
Docker 的 overlay 网络是一种基于 VXLAN(Virtual Extensible LAN)的多主机网络模式,专为 Docker Swarm 集群设计,用于实现跨节点的容器通信。它通过虚拟二层网络,允许容器在不同主机上像在同一局域网内一样通信。Dock…...
开发基于python的商品推荐系统,前端框架和后端框架的选择比较
开发一个基于Python的商品推荐系统时,前端和后端框架的选择需要综合考虑项目需求、开发效率、团队熟悉度以及系统的可扩展性等因素。 以下是一些推荐的框架和建议: 后端框架 Flask 优点: 轻量级:Flask的核心非常简洁,…...
CSRF 请求伪造Referer 同源置空配合 XSSToken 值校验复用删除
#CSRF- 无检测防护 - 检测 & 生成 & 利用(那数据包怎么整 找相似源码自己搭建整) 检测:黑盒手工利用测试,白盒看代码检验(有无 token ,来源检验等) 生成: BurpSuite->Engagement t…...
Datawhale AI春训营】AI + 新能源(发电功率预测)Task1
赛题链接 官网 新能源发电功率预测赛题进阶方案 下面是ai给的一些建议 新能源发电功率预测赛题进阶方案 一、时序特性深度挖掘 1. 多尺度周期特征 # 分钟级周期编码 train[15min_index] (train[hour]*4 train[minute]//15)# 周周期特征 train[weekday] pd.to_datetime…...
@EnableAsync+@Async源码学习笔记之二
从本文开始,就正式进入源码追踪阶段了,上一篇的最后我们提到了 EnableAsync 注解上的 Import(AsyncConfigurationSelector.class)了,本文就来看下它,源码如下: package org.springframework.scheduling.annotation;im…...
C++ STL 环形队列模拟实现
C STL 环形队列模拟实现 下面是一个使用C STL实现的环形队列(Circular Queue)的完整示例: #include <iostream> #include <vector> #include <stdexcept>template <typename T> class CircularQueue { private:std…...
每天五分钟深度学习PyTorch:0填充函数在搭建神经网络中的应用
本文重点 在深度学习中,神经网络的搭建涉及对输入数据、权重矩阵以及中间计算结果的处理。masked_fill 是 PyTorch 等深度学习框架中常用的张量操作函数,它通过布尔掩码(mask)对张量中的指定元素进行填充。当将矩阵元素填充为 0 时,masked_fill 在神经网络中发挥着重要作…...
pycharm中怎么解决系统cuda版本高于pytorch可以支持的版本的问题?
在PyCharm中安装与系统CUDA版本不一致的PyTorch是可行的。以下是解决方案的步骤: 1. 确认系统驱动兼容性 检查NVIDIA驱动支持的CUDA版本:运行 nvidia-smi,右上角显示的CUDA版本是驱动支持的最高版本。只要该版本不低于PyTorch所需的CUDA版本…...
【概率论】条件期望
在高等概率论中,给定一个概率空间 ( Ω , F , P ) (\Omega, \mathcal{F}, P) (Ω,F,P) 和其子 σ \sigma σ-代数 G ⊆ F \mathcal{G} \subseteq \mathcal{F} G⊆F,随机变量 X X X 关于 G \mathcal{G} G 的 条件期望 E [ X ∣ G ] E[X|\mathcal{G}…...
【java实现+4种变体完整例子】排序算法中【计数排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格
以下是计数排序的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格: 一、计数排序基础实现 原理 通过统计每个元素的出现次数,按顺序累加得到每个元素的最终位置,并填充到结果数组中。 代码示…...
Qt C++ 解析和处理 XML 文件示例
使用 Qt C 解析和处理 XML 文件 以下是使用 Qt C 实现 XML 文件处理的几种方法,包括解析、创建和修改 XML 文件。 1. 使用 QXmlStreamReader (推荐方式) #include <QFile> #include <QXmlStreamReader> #include <QDebug>void parseXmlWithStr…...
在服务器上部署MinIO Server
MinIO的优势 高性能:MinIO号称是目前速度最快的对象存储服务器,据称在标准硬件上,对象存储的读/写速度最高可以高达183 GB/s和171 GB/s,可惜我的磁盘跟不上 兼容性:MinIO基于Amazon S3协议,并提供了与S3兼…...
第二十七讲:AI+农学导论
关键词:人工智能、农业、作物识别、遥感、机器学习、案例实战 目录 📌 一、为什么农业需要人工智能? 📈 二、AI在农学中的典型应用场景 🧪 三、实战案例:AI识别作物类型(以随机森林为例) ✅ 数据集:iris(模拟作物种类识别) 📦 所需包: 🚀 数据准备: …...
医院科研科AI智能科研支撑平台系统设计架构方案探析
一、系统设计概述 1.1 系统定位 本系统是基于MCP(Model Context Protocol,模型上下文协议)协议构建的智能科研支撑平台,旨在为医院科研科室提供全流程AI辅助能力,覆盖课题立项、数据采集、分析建模到成果转化的完整科研生命周期。系统通过MCP协议实现与医院信息系统的深…...
Python基础总结(七)之条件语句
文章目录 条件语句if一、Python中的真假二、条件语句格式2.1 if语句格式2.2 if-else语句2.3 if-elif-else语句 三、if语句嵌套 条件语句if 条件语句其实就是if语句,在讲解if语句之前需要知道Python中对于真假的判断。 一、Python中的真假 在Python中非0的都为真&…...
Day10【基于encoder- decoder架构实现新闻文本摘要的提取】
实现新闻文本摘要的提取 1. 概述与背景2.参数配置3.数据准备4.数据加载5.主程序6.预测评估7.生成效果8.总结 1. 概述与背景 新闻摘要生成是自然语言处理(NLP)中的一个重要任务,其目标是自动从长篇的新闻文章中提取出简洁、准确的摘要。近年来…...
深度解析算法之二分查找(2)
17.二分查找 题目链接 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 示例 1: 输入: nums [-1,0,3,5,9,12], target…...
前端工程化之自动化测试
自动化测试 自动化测试为什么需要测试?什么时候需要考虑测试测试类型前端测试框架单元测试Jest 重点掌握项目示例package.jsonsrc/utils/math.tssrc/utils/math.test.ts进行测试jest.config.js覆盖率直观看覆盖率coverage/lcov-report/index.html src/main.test.tst…...
CANFD技术在新能源汽车通信网络中的应用与可靠性分析
一、引言 新能源汽车产业正处于快速发展阶段,其电子系统复杂度不断攀升,涵盖众多传感器、控制器与执行器。高效通信网络成为确保新能源汽车安全运行与智能功能实现的核心要素。传统CAN总线因带宽限制,难以满足高级驾驶辅助系统(A…...
【机器学习】朴素贝叶斯算法:原理剖析与实战应用
引言 朴素贝叶斯算法就像是一位善于从经验中学习的侦探,根据已有的线索来推断未知事件的概率。这是一种基于概率论的分类算法,以贝叶斯定理为基础,却做了一个"朴素"的假设:认为所有特征彼此独立。虽然这个假设在现实中…...
【更新完毕】2025妈妈杯C题 mathercup数学建模挑战赛C题数学建模思路代码文章教学:音频文件的高质量读写与去噪优化
完整内容请看文章最下面的推广群 我将先给出文章、代码、结果的完整展示, 再给出四个问题详细的模型 面向音频质量优化与存储效率提升的自适应编码与去噪模型研究 摘 要 随着数字媒体技术的迅速发展,音频处理技术在信息时代的应用愈加广泛,特别是在存储…...
UI键盘操作
1、Selenium中send_keys除了可以模拟键盘输入之外,还有些时候需要操作键盘上的按键,甚至是组合键,比如CTRLA,CTRLC等, 所以我们需要代码操作键盘。使用的是send_keys里的Keys的类。 from selenium.webdriver.common.keys import …...
【正则表达式】正则表达式使用总结
正则表达式除了匹配普通字符外,还可以匹配特殊字符,这些特殊字符被称为“元字符”。 特殊字符(元字符) 限定符:用于指定正则表达式中某个组件的出现次数。常见的限定符包括: *:0次或多次 +:1次或多次 ?:0次或1次 {n}:恰好n次…...
Qt编写推流程序/支持webrtc265/从此不用再转码/打开新世界的大门
一、前言 在推流领域,尤其是监控行业,现在主流设备基本上都是265格式的视频流,想要在网页上直接显示监控流,之前的方案是,要么转成hls,要么魔改支持265格式的flv,要么265转成264,如…...
Spring Boot 中基于 Reactor 的服务器端事件(SSE)推送机制实践
Spring Boot 3.0 中基于 Reactor 的服务器端事件(SSE)推送机制实践 在现代 Web 应用开发中,实时数据交互越来越成为刚需,从股票行情的实时更新到社交平台的消息即时推送,服务器端事件(Server-Sent Events,简称 SSE)作为一种高效的单向数据传输技术,正发挥着重要作用。…...
CRC实战宝典:从原理到代码,全面攻克循环冗余校验
CRC实战宝典:从原理到代码,全面攻克循环冗余校验 github开源:CRC软硬件协同测试项目 CRC 简介 CRC(循环冗余校验)是一种强大的错误检测技术,广泛应用于数字网络和存储系统。它是确保数据完整性的重要方法…...
【愚公系列】《Python网络爬虫从入门到精通》056-Scrapy_Redis分布式爬虫(Scrapy-Redis 模块)
🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! …...
ZLMediaKit 和 SRS的区别,哪个更好用?
ZLMediaKit 和 SRS(Simple RTMP Server)是两个主流的开源流媒体服务器框架,各自在功能、性能、适用场景等方面存在显著差异。以下是两者的对比分析及选择建议: 一、核心差异对比 协议支持 ZLMediaKit:支持更广泛的流媒…...
【PyTorch】colab上跑VGG(深度学习)数据集是 CIFAR10
跑得结果是测试准确率10%,欠拟合。 import torch import torchvision.datasets from torch import nn from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter from torchvision import datasets, transformstransform tran…...
pytorch 51 GroundingDINO模型导出tensorrt并使用c++进行部署,53ms一张图
本专栏博客第49篇文章分享了将 GroundingDINO模型导出onnx并使用c++进行部署,并尝试将onnx模型转换为trt模型,fp16进行推理,可以发现推理速度提升了一倍。为此对GroundingDINO的trt推理进行调研,发现 在GroundingDINO-TensorRT-and-ONNX-Inference项目中分享了模型导出onnx…...
编程语言基础 - C++ 面试题
C++ 面试题 tags: c++ 文章目录 C++ 面试题关键字1. const2. static3. this 指针4. inline 内联函数5. volatile6. struct, class7. enum关键字 1. const 修饰变量:该变量不能被改变 修饰指针: 指针常量: 指针本身是常量 TYPE* const pContent;指向常量的指针:指针所指向…...
JVM笔记【一】java和Tomcat类加载机制
JVM笔记一java和Tomcat类加载机制 java和Tomcat类加载机制 Java类加载 * loadClass加载步骤类加载机制类加载器初始化过程双亲委派机制全盘负责委托机制类关系图自定义类加载器打破双亲委派机制 Tomcat类加载器 * 为了解决以上问题,tomcat是如何实现类加载机制的…...
Python----深度学习(全连接与链式求导法则)
一、机器学习和深度学习的区别 机器学习:利用计算机、概率论、统计学等知识,输入数据,让计算机学会新知 识。机器学习的过程,就是训练数据去优化目标函数。 深度学习:是一种特殊的机器学习,具有强大的能力和…...
基于SpringBoot的网上找律师管理系统
博主介绍:java高级开发,从事互联网行业六年,熟悉各种主流语言,精通java、python、php、爬虫、web开发,已经做了六年的毕业设计程序开发,开发过上千套毕业设计程序,没有什么华丽的语言࿰…...
《目标检测双雄:YOLO与Faster R-CNN,谁主沉浮?》
在计算机视觉的广阔天地里,目标检测技术宛如一颗璀璨的明星,照亮了无数应用场景。从安防监控中对行人与车辆的精准识别,到自动驾驶领域对道路障碍物的快速判断,再到工业生产里对产品缺陷的严格检测,目标检测无处不在&a…...
CUDA编程中影响性能的小细节总结
一、内存访问优化 合并内存访问:确保相邻线程访问连续内存地址(全局内存对齐访问)。优先使用共享内存(Shared Memory)减少全局内存访问。避免共享内存的Bank Conflict(例如,使用padding或调整访…...
C#学习第17天:序列化和反序列化
什么是序列化? 定义:序列化是指把对象转换为一种可以轻松存储或传输的格式,如JSON、XML或二进制格式。这个过程需要捕获对象的类型信息和数据内容。用途:使得对象可以持久化到文件、发送至网络、或存储在数据库中。 什么是反序列…...
kafka的零拷贝技术
在 Kafka 中,高性能数据传输依赖于操作系统提供的 零拷贝(Zero-Copy) 技术,主要包括 sendfile 和 mmap 两种实现方式。它们的核心目标是减少数据在用户态和内核态之间的拷贝次数,从而提升 I/O 效率。下面详细解析它们的…...
从 0~1 保姆级 详细版 PostgreSQL 数据库安装教程
PostgreSQL数据库安装 PostgreSQL官网 【PostgreSQL官网】 | 【PostgreSQL安装官网_Windows】 安装步骤 step1: 选择与电脑相对应的PostgreSQL版本进行下载。 step2: 双击打开刚才下载好的文件。 step3: 在弹出的setup窗口中点击 …...
MySQL中常用函数的分类及示例
概述 以下是 MySQL 中常用函数的分类及示例,涵盖字符串处理、数值计算、日期操作、条件判断等常见场景: 一、字符串函数 1. CONCAT(str1, str2, ...) 拼接字符串。 SELECT CONCAT(Hello, , World); -- 输出: Hello World2. SUBSTRING(str, start,…...
【论文阅读21】-PSOSVM-CNN-GRU-Attention-滑坡预测(2024-12)
这篇论文主要提出并验证了一种新型的混合智能模型(PSOSVM-CNN-GRU-Attention),用于准确预测滑坡的点位移,并构建可靠的位移预测区间。通过对Baishuihe滑坡和Shuping滑坡的案例分析,展示了该模型的出色性能。 [1] Zai D…...