C语言基础(二十七)

1、位字段(Bit-fields)也是一种数据结构,允许在结构体(struct)或联合体(union)中定义其成员占用特定的位数。对于需要精确控制内存布局或处理硬件寄存器映射等场景非常有用。位字段使得开发者能够定义小于一个字节的变量,从而更有效地利用内存空间。位字段的声明方式是在结构体或联合体的成员后面加上冒号和该成员所占的位数。

测试代码:

#include <stdio.h>  
// 温馨提示:本程序不能在实际的硬件环境中运行,仅做示例。
// 位字段 
// 硬件寄存器结构体  
struct hardware_registers {  unsigned int control: 1;  // 控制位  unsigned int mode: 2;     // 模式选择位unsigned int speed: 3;    // 速度控制位unsigned int : 0;         // 填充位,不占用空间  unsigned int status: 1;   // 状态位,只读  // 其他寄存器...  // unsigned int another_register: 8;  
};  // 硬件寄存器地址(硬件的物理地址,代码无法直接运行,0x12345678不是一个有效的硬件地址。)   
volatile struct hardware_registers *hardware = (volatile struct hardware_registers *)0x12345678;  // 写入硬件寄存器的函数  
void write_hardware_register(void) {  // 设置控制位为1,模式为2(从0开始计数),速度为4(同样从0开始)  hardware->control = 1;  hardware->mode = 2;  hardware->speed = 4;  // 检查写入是否成功(需要读取状态寄存器)  // check_hardware_status();  
}  // 读取硬件状态并打印的函数  
void read_hardware_status(void) {  // 读取状态位 if (hardware->status) {  printf("Hardware is in active state.\n");  } else {  printf("Hardware is in inactive state.\n");  }  
}  int main() {  // 写入硬件寄存器  write_hardware_register();  // 读取并打印硬件状态  read_hardware_status();  return 0;  
}  

.........................................................................................................................................................   

2、邻接表通过为每个顶点维护一个链表来存储与该顶点相邻的所有顶点,从而高效地存储和访问图中的边。 

测试代码:

#include "date.h" 
#include <stdio.h>  
#include <stdlib.h>   
#define MAX_VERTICES 100  
// AdjListNode 表示邻接表中的一个节点,包含目标顶点和指向下一个节点的指针。 
typedef struct AdjListNode {  int dest;  struct AdjListNode* next;  
} AdjListNode;  
// AdjList 包含一个指向邻接表头部的指针。 
typedef struct AdjList {  struct AdjListNode* head; 
} AdjList;  
//  Graph是一个结构体(struct),表示图论中的图。
// 结构体通常会包含顶点的数组(或指针数组)以及某种形式表示边(比如:邻接矩阵、邻接表等)。// Graph 包含顶点数和一个指向邻接表数组的指针。
typedef struct Graph {  int V;  struct AdjList* array;  
} Graph;  // 函数声明 
void addEdge(Graph* graph, int src, int dest);  
void printGraph(Graph* graph);  
void DFS(Graph* graph, int v, int visited[]);  
void BFS(Graph* graph, int s);  // newAdjListNode 函数:创建一个新的邻接表节点,其中 dest 参数表示目标顶点。
// 使用动态内存分配分配一个新的节点,并将目标顶点赋值给新节点的 dest 字段,
// 并将 next 字段设为 NULL。最后返回新节点的指针。
// 函数定义开始,接收一个整型参数dest,返回一个指向AdjListNode类型的指针  
AdjListNode* newAdjListNode(int dest) {  // 使用malloc函数动态分配内存给一个新的AdjListNode结构体实例  // sizeof(AdjListNode)计算AdjListNode结构体所需的总字节数  // (AdjListNode*)类型转换,将void*类型的malloc返回值转换为AdjListNode*类型  // 分配的内存地址被存储在newNode指针中  AdjListNode* newNode = (AdjListNode*) malloc(sizeof(AdjListNode));  // 将传入的dest参数赋值给新节点的dest成员变量  // dest成员变量通常用于存储与该节点相关联的顶点或边的信息  newNode->dest = dest;  // 初始化新节点的next指针为NULL  // next指针用于指向链表中的下一个节点,初始时为NULL表示链表结束  newNode->next = NULL;  // 返回新创建的节点指针  return newNode;  
} 
// createGraph 函数:创建一个新的图,其中 vertices 参数表示图中顶点的数量。
// 首先分配一个 Graph 结构体的空间,然后设置顶点的数量。
// 然后再分配一个邻接表数组的空间,并对每个邻接表头部进行初始化。
// 最后返回创建的图的指针。
// vertices 作为参数,表示图中顶点的数量。函数返回一个指向 Graph 类型的指针。 
Graph* createGraph(int vertices) {  // 为 Graph 结构体分配内存,并将返回的指针存储在 graph 变量中。(Graph*) 类型转换,将 void* 转换(Graph*) 指针类型。 Graph* graph = (Graph*) malloc(sizeof(Graph)); // 将图的顶点数(vertices)存储在 graph 结构的 V 成员中。 graph->V = vertices;  // 为AdjList 类型的数组分配内存,数组的大小与图的顶点数相同。// 每个 AdjList 元素(为一个链表头,每个链表包含从该顶点出发的所有边的目标顶点)对应于图中的一个顶点。 graph->array = (AdjList*) malloc(vertices * sizeof(AdjList));  // 遍历邻接表数组,将每个 AdjList 的 head 成员初始化为 NULL。// 创建图时,没有任何边存在(每个顶点的邻接链表都是空的)。for (int i = 0; i < vertices; ++i) graph->array[i].head = NULL;  return graph;  
}
// addEdge 函数:向图中添加一条边,从顶点 src 到 dest。
// 首先创建一个新的邻接表节点,然后将该节点插入到 src 对应的邻接表中,
// 由于图是无向图,需要在 dest 对应的邻接表中插入一条边从 dest 指向 src。
void addEdge(Graph* graph, int src, int dest) {  // 将 dest 成员设置为给定的参数值,然后返回指向该节点的指针,创建一个新节点,// 该节点的 dest 成员被设置为当前边的目标顶点 dest。AdjListNode* newNode = newAdjListNode(dest);  // 将新节点的 next 指针设置为源顶点 src 当前邻接链表的头节点。// 将源顶点 src 的邻接链表头指针 head 更新为新节点,从而将该新节点添加到链表的开头。// 表示从源顶点 src 到目标顶点 dest 有一条边。newNode->next = graph->array[src].head;  graph->array[src].head = newNode;  // 将新节点添加到目标顶点 dest 的邻接链表中。// 表示从目标顶点 dest 到源顶点 src 也有一条边,无向图的特性。 newNode = newAdjListNode(src);  newNode->next = graph->array[dest].head;  graph->array[dest].head = newNode;  
}
//  DFS 函数:深度优先搜索。
// 从给定的起始顶点 v 开始,递归地遍历与它相邻的顶点,直到没有未访问的相邻顶点。
// 递归函数将递归访问每个相邻顶点,并用 visited 数组跟踪已访问的顶点。
void DFS(Graph* graph, int v, int visited[]) {  // 将整数数组 visited 中索引为 v 的元素设置为 1,表示顶点 v 已经被访问过。visited[v] = 1;  // 打印当前正在访问的顶点 v 的值printf("%d", v);  // 获取图中顶点 v 的邻接链表的头节点,并将其地址存储在指针 temp 中。 AdjListNode* temp = graph->array[v].head;  //  while 循环遍历顶点 v 的所有邻接顶点。// 循环继续执行,直到 temp 变为 NULL,遍历完所有邻接顶点。 while (temp) {  // 获取当前邻接链表节点 temp 的目标顶点 next。int next = temp->dest;  // 检查该顶点是否已经被访问过(即 visited[next] 是否为 0)。if (!visited[next])  // 如果 next 顶点尚未被访问,则递归调用 DFS 函数,以 next 为新的起始顶点继续搜索。 DFS(graph, next, visited);  // 将 temp 更新为当前节点的下一个节点,以下一次循环迭代中处理。// 确保能够遍历完顶点 v 的所有邻接顶点。temp = temp->next;  } // 当 temp 变为 NULL 时,while 循环结束,表示顶点 v 的所有邻接顶点都已经被检查并已经被递归访问过。 
}  
// BFS 函数:广度优先搜索。
// 从给定的起始顶点 s 开始,利用队列依次访问和处理与起始顶点相邻的顶点,直到队列为空。
// while循环,函数将访问起始顶点的相邻顶点,并将们添加到队列中,同时使用 visited 数组跟踪已访问的顶点。 
void BFS(Graph* graph, int s) {  // 声明整数数组 visited,其大小为图的顶点数 graph->V。用于跟踪哪些顶点已经被访问过。int visited[graph->V];  // 循环遍历 visited 数组,将所有元素初始化为 0,表示开始时没有顶点被访问过。for (int i = 0; i < graph->V; i++)  visited[i] = 1;  // 声明整数数组 queue 作为队列,用于存储待访问的顶点。// 声明两个整数 front 和 rear 分别作为队列的前端和尾端索引,初始时都设为 0。int queue[graph->V], front = 0, rear = 0;  // 将起始顶点 s 标记为已访问(将 visited[s] 设置为 1)。// 将起始顶点 s 加入队列的尾部(通过增加 rear 索引并将 s 赋值给 queue[rear])。visited[s] = 1;  queue[rear++] = s;  // 循环持续进行,直到队列为空(即 front 等于 rear)。// 在队列不为空的情况下,执行循环体内的代码。while (front < rear) { // 从队列的前端取出一个顶点 s(通过增加 front 索引并读取 queue[front] 的值),并打印出来。表示顶点 s 已经被访问。 s = queue[front++];printf("%d", s);  // 对于每个邻接顶点,如果未被访问(即 visited[temp->dest] 为 0),则将其标记为已访问,并将其加入队列的尾部。// 通过遍历 s 的邻接链表(由 graph->array[s].head 指向)实现,其中 temp 是指向邻接链表节点的指针。AdjListNode* temp = graph->array[s].head;  while (temp) {  if (!visited[temp->dest]) {  visited[temp->dest] = 1;  queue[rear++] = temp->dest;  }  temp = temp->next;  }  }  
}// 释放链表中所有节点  
void freeAdjList(AdjList* adjList) {  // 指向AdjListNode类型的指针temp。用于临时存储链表中当前要释放的节点的地址。AdjListNode* temp;// 邻接表的头节点不为空(即链表中还有节点未被释放),循环继续执行。  while (adjList->head != NULL) {  // 将adjList->head(即当前链表的头节点)的地址赋值给temp。// temp指向当前要释放的节点。temp = adjList->head;  // adjList->head更新为adjList->head->next,让头节点指向下一个节点。 adjList->head = adjList->head->next;  // 释放temp所指向的内存 free(temp);  }  
}  // 释放图占用的所有内存  
void freeGraph(Graph* graph) {  // 释放每个顶点的邻接表  for (int i = 0; i < graph->V; i++) {  freeAdjList(&graph->array[i]);  }  // 释放顶点数组  free(graph->array);  // 释放图结构本身  free(graph);  
}  int main() {  int time = getTime();int V = 4; // 图的顶点数  Graph* graph = createGraph(V);  printf("Adding edges:\n");  addEdge(graph, 0, 1);  addEdge(graph, 0, 2);  addEdge(graph, 1, 2);  addEdge(graph, 2, 0); // 冗余,无向图已经通过addEdge添加了从0到2和从2到0的边。 addEdge(graph, 2, 3);  addEdge(graph, 3, 3); // 添加一个自环。 printf("\nGraph created. Following is Depth First Traversal (DFS):\n");  int* visited = (int*)malloc(V * sizeof(int));  if (visited == NULL) {  fprintf(stderr, "Memory allocation failed\n");  exit(EXIT_FAILURE);  }  for (int i = 0; i < V; i++)  if (visited[i] == 0)  DFS(graph, i, visited); // 从每个未访问的顶点开始DFS  // 重置visited数组进行BFS  for (int i = 0; i < V; i++)  visited[i] = 0;  printf("\nFollowing is Breadth First Traversal (BFS), starting from vertex 2:\n");  BFS(graph, 2); // 从顶点2开始BFS  // 清理分配的内存  freeGraph(graph);  return 0;  
}

运行结果如下:

 

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

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

相关文章

WebRTC协议下的视频汇聚融合技术:EasyCVR视频技术构建高效视频交互体验

视频汇聚融合技术是指将来自不同源、不同格式、不同网络环境的视频流进行集中处理、整合和展示的技术。随着视频监控、远程会议、在线教育、直播娱乐等领域的快速发展&#xff0c;视频数据的规模急剧增长&#xff0c;对视频处理能力和效率提出了更高要求。视频汇聚融合技术通过…

GAMES202——作业3 Screen Space Ray Tracing

任务 为场景实现屏幕空间的全局光照效果 1.直接光照&#xff1a; 实现ssrFragmentShader中的EvalDiffuse(wi, wo, uv) 和EvalDirectionalLight(uv) 函数&#xff0c;并在 main 函数中实现直接光照的效果。 2.屏幕空间光线求交&#xff1a;实现RayMarch(ori, dir, out hitPos) …

C语言初阶 --- 数据在内存中的存储

&#x1f388; 个人主页&#x1f449;&#xff1a;tbRNA-CSDN博客 &#x1f4af; 个人简介&#xff1a;在校大学生一枚&#x1f48b;. &#x1f60d; 希望我的文章对大家有着不一样的帮助&#xff0c;欢迎大家关注我&#xff0c;感谢大家的多多支持&#xff01; &#x1f389; …

前端面试题每日一练,测测你对JavaScript对象继承和 Object.entries() 的理解

今天的挑战题目涉及到JavaScript中的原型链 (prototype chain) 和 Object.entries() 方法的使用。我们将通过一个对象继承的例子来探索如何使用 Object.entries() 获取对象的自身可枚举属性&#xff0c;并进行处理。让我们一起分析这段代码&#xff0c;看看它会输出什么以及为什…

碎碎念之Android中CPU架构arm-v8a、arm-v7a、x86

0 碎碎念 之前写博客都是为了复习基础知识&#xff0c;不过好像也忘得很快hh。 以后估计会写点感兴趣的自己碎碎念&#xff0c;缓解下emo的心情。&#xff08;不像之前的博客&#xff0c;这些博客不准备复现也不贴代码所以不一定对&#xff0c; 仅供个人参考 &#xff09; 现在…

JMeter Plugins之内网插件问题解决

JMeter Plugins之内网插件问题解决 背景 在我司内部进行JMeter工具进行性能脚本开发时&#xff0c;为了提高测试效率&#xff0c;我们会用到部分JMeter提供的插件&#xff0c;但是在我司内网的情况下&#xff0c;我们如果直接点击JMeter界面右上角的插件按钮 弹出来的JMeter…

Python-MNE-源空间和正模型07:修复BEM和头表面

有时在创建BEM模型时&#xff0c;由于可能出现的一系列问题(例如&#xff0c;表面之间的交叉)&#xff0c;表面需要手动校正。在这里&#xff0c;我们将看到如何通过将表面导出到3D建模程序blender&#xff0c;编辑它们&#xff0c;并重新导入它们来实现这一点。我们还将给出一…

图形化编程系统学习10

项目需求&#xff1a; 点击绿旗&#xff0c;可以使用键盘控制小兔子在地图上移动&#xff0c;收集食物&#xff0c;但只能在黄色道路上移动。 食物碰到小兔子会变大后隐藏&#xff0c;并发出声音。 收集完所有食物&#xff0c;回到温暖的小窝 。 思路解析 1、添加背景和角色…

事半功倍:利用增强现实提高工作效率

人们通常认为增强现实只是游戏中的一个强大的功能&#xff0c;然而&#xff0c;研究表明&#xff0c;增强现实在提高工厂的效率和生产力方面也发挥着重要作用。不管增强现实、虚拟现实还是混合现实都能很好地模拟工厂的工作场景&#xff0c;这对于培训、运营、安全和研发方面的…

OpenCV小练习:人脸检测

OpenCV自带人脸检测模型&#xff0c;拿来就能用。所以“人脸检测”这个任务对于OpenCV而言真是太简单了——感叹一下&#xff1a;OpenCV太强大了&#xff01;相关的介绍文章在网上可以搜到很多&#xff0c;原本我觉得没必要再写一篇了。结果我在写练习代码的时候&#xff0c;还…

如何使用 Pytest 进行测试

Pytest 是一个强大的Python测试框架&#xff0c;支持简单单元测试和复杂的功能测试。它具有灵活的断言表达式、支持参数化测试、强大的插件生态系统等特点。 二、环境搭建 1、安装 Pytest&#xff1a; pip install pytest安装完成后&#xff0c;可以通过命令行检查是否安装成…

Adobe DC 2022提示无法识别的错误 - 解决方案

Adobe DC 2022提示无法识别的错误 - 解决方案 问题解决方案更改安装&#xff08;推荐&#xff09;重新安装&#xff08;推荐&#xff09;降级安装&#xff08;不推荐&#xff09; 问题 使用Adobe DC 2022合并图片创建PDF时&#xff0c;会提示无法识别的错误&#xff0c;这是因…

同步技术难点

在Java中&#xff0c;同步技术主要用于控制多个线程对共享资源的访问&#xff0c;以避免数据不一致和线程安全问题。然而&#xff0c;同步技术也带来了一些难点&#xff0c;主要包括以下几个方面&#xff1a; 死锁&#xff08;Deadlock&#xff09;&#xff1a; 死锁是同步技术…

Python私教张大鹏FastAPI开源框架和项目第一次整理 20240830

去我的Github搜fastzdp开头的&#xff1a;https://github.com/zhangdapeng520?tabrepositories&qfastzdp&type&language&sort fastzdp_api&#xff1a;基于FastAPI二次开发的HTTP REST API 框架。目前刚开始开发&#xff0c;这里面主要记录了FastAPI的一些基础…

大一新生入学证件照采集,手机拍照轻松搞定收集

又到了一年一度大中专院校新生入学的时候了&#xff0c;在开学时很重要的一项工作就是新生照片采集。证件照采集是为了建立学生学籍档案、校园门禁系统登记、校园卡制发、大学四级英语考试报名等&#xff0c;往往要求全校新生使用统一的证件照尺寸、颜色背景&#xff0c;甚至是…

Access OpenAI (json) API from R

题意&#xff1a;“从 R 访问 OpenAI (JSON) API” 问题背景&#xff1a; I want to access the OpenAI API with the following curl command from R: “我想从 R 中使用以下 curl 命令访问 OpenAI API&#xff1a;” curl https://api.openai.com/v1/engines/davinci/comp…

视频结构化从入门到精通——行为分析类应用

行为分析类应用 1. 认识行为分析 监控/判断视频画面中目标的运动过程、携带属性等。从数据中自动识别、跟踪和理解人类或物体行为。 1. 车的行为分析应用 车辆行为分析主要用于监控和管理车辆的动态行为&#xff0c;广泛应用于智能交通、城市管理和安全监控。关键应用包括&…

操作系统:实验五内存管理实验

一、实验目的 1、了解操作系统动态分区存储管理过程和方法。 2、掌握动态分区存储管理的主要数据结构--空闲表区。 3、加深理解动态分区存储管理中内存的分配和回收。 4、掌握空闲区表中空闲区3种不同放置策略的基本思想和实现过程。 5、通过模拟程序实现动态分区存储管理…

如何通过WinRAR软件有效禁止RAR压缩包内文件的修改

RAR压缩包作为一种广泛使用的文件格式&#xff0c;凭借其高压缩比和强大的功能&#xff0c;成为了许多用户保存和传输文件的首选。然而&#xff0c;在某些情况下&#xff0c;我们可能希望确保RAR压缩包内的文件不被随意修改或删除&#xff0c;以维护文件的安全性和完整性。本文…

C++:list篇

前言: 观看C的list前需要对链表有一些了解&#xff0c;如C语言的链表结构。本片仅介绍list容器中常用的接口函数概念以及使用。 list的概念&#xff1a; 简而言之&#xff0c;C的list是一个双向带哨兵位的链表容器模板 list的构造&#xff1a; 1.list():默认构造 2.li…