数据结构(三)循环链表 约瑟夫环

文章目录

  • 一、循环链表
    • (一)概念
    • (二)示意图
    • (三)操作
      • 1. 创建循环链表
        • (1)函数声明
        • (2)注意点
        • (3)代码实现
      • 2. 插入(头插,尾插,任意位置插入)
        • (1)头插
          • ① 函数声明
          • ② 注意点
          • ③ 代码实现
        • (2)尾插
          • ① 函数声明
          • ② 注意点
          • ③ 代码实现
        • (3)任意位置插入
          • ① 函数声明
          • ② 注意点
          • ③ 代码实现
      • 3. 删除(头删,尾删,任意位置删除)
        • (1)头删
          • ① 函数声明
          • ② 注意点
          • ③ 代码实现
        • (2)尾删
          • ① 函数声明
          • ② 注意点
          • ③ 代码实现
        • (3)任意位置删除
          • ① 函数声明
          • ② 注意点
          • ③ 代码实现
      • 4. 修改
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 5. 查询
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 6. 清空和销毁
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 7. 打印链表(方便查看实验现象)
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 8. 排序(以正序排序为例)
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 9.剔重
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
    • (四)应用:实现约瑟夫环
      • 1.问题描述
      • 2. 问题分析
      • 3. 代码实现
      • 4. 使用前面的循环链表实现
  • 二、代码源码已上传资源

一、循环链表

(一)概念

操作和单向链表的操作基本一样
只是判断链表结束的条件不同

循环链表又分为有头循环链表和无头循环链表,其中无头结点的循环链表相对更常见些,因此下文以实现无头循环链表为例。

(二)示意图

在这里插入图片描述

(三)操作

结构体定义:

//数据元素结构体
typedef struct circle_node
{int data;struct circle_node *next;
}nd_t;//数据对象结构体
typedef struct circle_list
{nd_t *phead; //指向头节点//还可以添加其他成员
}list_t;

1. 创建循环链表

(1)函数声明

int create_list(list_t **my_list);

创建循环链表的第一个节点,
第一个节点的next指向它自己
将第一个节点的堆区地址传给main函数中的指针

(2)注意点
  1. 入参不能为空
  2. 因为需要将申请的第一个节点的地址写入main函数中的指针变量中,因此必须传入二级指针
  3. 申请内存空间后检查是否申请成功
(3)代码实现
int create_list(list_t **my_list){if(NULL==my_list){return -1;}*my_list=(list_t *)malloc(sizeof(list_t));if(NULL==*my_list){return -1;}(*my_list)->phead=NULL;return 0;
}

2. 插入(头插,尾插,任意位置插入)

(1)头插
① 函数声明

int insert_list_by_head(list_t *my_list,int num);

创建新节点
找到尾节点,将尾节点的next指向新的节点
新节点的next指向首节点
*phead指向pnew

② 注意点
  1. 入参不能为NULL
  2. 头插需要更改main函数中phead指针的值,因此需要传二级指针
  3. 需要保证链表中至少有一个节点,无头链表中只要phead不为NULL,就说明至少有一个节点
③ 代码实现
int insert_list_by_head(list_t *my_list,int num){//入参不合理if(NULL==my_list)return -1;//创建新节点nd_t *pnew=(nd_t *)malloc(sizeof(nd_t));if(NULL==pnew)return -1;pnew->data=num;//插入首节点if(NULL==my_list->phead){my_list->phead=pnew;pnew->next=pnew;return 0;}//如果插入的不是第一个节点//先找到尾节点nd_t *ptemp=my_list->phead;while(ptemp->next!=my_list->phead){ptemp=ptemp->next;}//插入ptemp->next=pnew;pnew->next=my_list->phead;my_list->phead=pnew;return 0;
}
(2)尾插
① 函数声明

int insert_list_by_tail(list_t *my_list,int num);

创建新节点
找到尾节点,将尾节点的next指向新的节点
新节点的next指向首节点

② 注意点
  1. 头插和尾插的区别仅在于是否需要修改main函数中的指针变量
③ 代码实现
int insert_list_by_tail(list_t *my_list,int num){if(NULL==my_list)return -1;//创建新节点nd_t *pnew=(nd_t *)malloc(sizeof(nd_t));if(NULL==pnew)return -1;pnew->data=num;//插入首节点if(NULL==my_list->phead){my_list->phead=pnew;pnew->next=pnew;return 0;}//找到尾节点nd_t *ptemp=my_list->phead;while(ptemp->next!=my_list->phead){ptemp=ptemp->next;}//插入ptemp->next=pnew;pnew->next=my_list->phead;return 0;
}
(3)任意位置插入
① 函数声明

int insert_list_by_pos(list_t *my_list,int pos,int num);

找到要插入的位置的前一个节点
创建新节点
插入节点

② 注意点
  1. 不支持插入在第一个位置
  2. 如果插入的前一个位置在最后一个可以,但是在第一个就不合理了
③ 代码实现
int insert_list_by_pos(list_t *my_list,int pos,int num){if(NULL==my_list)return -1;if(pos<0)return -1;//找到要插入的节点的前一位nd_t *ptemp=my_list->phead;int i=0;//记录ptemp移动了几步while(ptemp->next!=my_list->phead){if(i==pos-1) break; ptemp=ptemp->next;i++;}//如果已经到尾节点了还没移动到pos位置就说明位置不合理if(i<pos-1){printf("位置不合理\n");return -1;}//创建新节点nd_t *pnew=(nd_t *)malloc(sizeof(nd_t));if(NULL==pnew)return -1;pnew->data=num;//插入第一个节点if(NULL==my_list->phead){my_list->phead=pnew;pnew->next=pnew;return 0;}//插入到头节点if(0==pos){nd_t *ptail=my_list->phead;while(ptail->next!=my_list->phead)ptail=ptail->next;ptail->next=pnew;pnew->next=my_list->phead;my_list->phead=pnew;return 0;}//插入节点pnew->next=ptemp->next;ptemp->next=pnew;return 0;
}

3. 删除(头删,尾删,任意位置删除)

(1)头删
① 函数声明

delete_list_by_head(list_t *my_list);

找到尾节点
尾节点的next置成*phead->next
*phead=*phead->next
free(pdef)

② 注意点
  1. 需要传入二级指针
  2. 当表中只有一个节点时,进行删除操作时相当于将表销毁了。
③ 代码实现
int delete_list_by_head(list_t *my_list){//传参为空或者表为空if(NULL==my_list||NULL==my_list->phead)return -1;//只有一个节点if(my_list->phead->next==my_list->phead){free(my_list->phead);my_list->phead=NULL;printf("表已清空\n");return 0;}//多个节点//找到尾节点nd_t *ptemp=my_list->phead->next;while(ptemp->next!=my_list->phead){ptemp=ptemp->next;}//头删nd_t *pdel=my_list->phead;my_list->phead=my_list->phead->next;ptemp->next=my_list->phead;free(pdel);pdel=NULL;return 0;
}
(2)尾删
① 函数声明

int delete_list_by_tail(list_t *my_list);

找到尾节点的前一节点,
尾删操作

② 注意点
  1. 需要传入二级指针
  2. 当表中只有一个节点时,进行删除操作时相当于将表销毁了。
③ 代码实现
int delete_list_by_tail(list_t *my_list){//传参为空或者表为空if(NULL==my_list||NULL==my_list->phead)return -1;//只有一个节点if(my_list->phead->next==my_list->phead){free(my_list->phead);my_list->phead=NULL;printf("表已清空\n");return 0;}//多个节点//找到尾节点的前一个节点nd_t *ptemp=my_list->phead->next;while(ptemp->next->next!=my_list->phead){ptemp=ptemp->next;}//尾删nd_t *pdel=ptemp->next;ptemp->next=my_list->phead;free(pdel);pdel=NULL;return 0;
}
(3)任意位置删除
① 函数声明

int delete_list_by_pos(list_t *my_list,int pos);

② 注意点
  1. 链表中至少有一个节点
  2. 如果只有一个节点时要删除第0个位置可以成功,此时链表销毁;其他位置均为不合理
  3. 如果多个节点时,需要区分是不是要删除头节点
  4. ptemp是要删除的节点的前一个节点,它不能是尾节点
③ 代码实现
int delete_list_by_pos(list_t *my_list,int pos){//传参为空或者表为空if(NULL==my_list||NULL==my_list->phead)return -1;if(0>pos){return -1;}//如果链表中只有一个节点if(my_list->phead->next==my_list->phead){//删除第一个位置的节点if(0==pos){free(my_list->phead);my_list->phead=NULL;return 0;}//删除其他位置节点,均是位置不合理printf("位置不合理\n");return -1;}//链表有多个节点nd_t *pdel=my_list->phead;//删除第一个位置的节点//找到尾节点nd_t *ptemp=my_list->phead;while(ptemp->next!=my_list->phead){ptemp=ptemp->next;}if(0==pos){my_list->phead=my_list->phead->next;ptemp->next=my_list->phead;free(pdel);pdel=NULL;return 0;}//删除其他位置节点//找到要删除的节点的前一个节点ptemp=my_list->phead;for(int i=0;i<pos-1;i++){//要删除的节点的前一个节点不能是尾节点if(ptemp->next->next==my_list->phead){printf("删除位置不合理\n");return -1;}ptemp=ptemp->next;}pdel=ptemp->next;ptemp->next=pdel->next;free(pdel);pdel=NULL;return 0;
}

4. 修改

(1)函数定义

int modify_list_by_pos(list_t *my_list,int pos,int num);

遍历链表找到第pos个位置

(2)注意点
  1. 如果已经到达尾节点就不能再继续向下遍历修改
(3)代码实现
int modify_list_by_pos(list_t *my_list,int pos,int num){//至少有一个节点if(NULL==my_list||NULL==my_list->phead)return -1;if(0>pos){return -1;}//找到第pos个位置nd_t *ptemp=my_list->phead;for(int i=0;i<pos;i++){if(ptemp->next==my_list->phead){printf("位置不合理\n");return -1;}ptemp=ptemp->next;}ptemp->data=num;return 0;
}

5. 查询

(1)函数定义

int search_list_by_pos(list_t *my_list,int pos,int *num);

找到第pos个位置
读取数据域数据

(2)注意点
  1. 查询和修改的唯一区别是对数据的处理,修改是将新的数据写到第pos尾的数据域;修改是将pos位的数据域写到num中
  2. 循环结束条件与修改和删除一样
(3)代码实现
int search_list_by_pos(list_t *my_list,int pos,int *num){//至少有一个节点if(NULL==my_list||NULL==my_list->phead||NULL==num)return -1;if(0>pos){return -1;}//找到第pos个位置nd_t *ptemp=my_list->phead;for(int i=0;i<pos;i++){if(ptemp->next==my_list->phead){printf("位置不合理\n");return -1;}ptemp=ptemp->next;}*num=ptemp->data;return 0;
}

6. 清空和销毁

(1)函数定义

int clean_list(list_t *my_list);
int destory_list(list_t **my_list);

先判断是不是只有一个节点
采用尾删(使用头删的话还要一直修改main函数中的指针变量的值)

(2)注意点
  1. 使用二级指针
  2. 入参不能为空
(3)代码实现
int clean_list(list_t *my_list){if(NULL==my_list){return -1;}//不止一个节点//采用头删,先找到尾节点前一个节点while(my_list->phead!=NULL){delete_list_by_head(my_list);}return 0;
}
int destory_list(list_t **my_list){if(NULL==my_list||NULL==*my_list){return -1;}clean_list(*my_list);//此时只有一个节点了free(*my_list);*my_list=NULL;return 0;
}

7. 打印链表(方便查看实验现象)

(1)函数定义

int print_list(list_t *my_list);

先打印出第一个节点,
遍历链表,直到ptemp->next==phead时结束

(2)注意点
  1. 在无头链表中phead为NULL,则说明表为空。phead->next==NULL,说明没有第二个节点。
(3)代码实现
int print_list(list_t *my_list){if(NULL==my_list)return -1;nd_t *ptemp=my_list->phead->next;//打印头节点printf("%d ",my_list->phead->data);//当ptemp==mylist->phead时,说明回到了开头while(ptemp!=my_list->phead){printf("%d ",ptemp->data);ptemp=ptemp->next;}putchar(10);return 0;
}

8. 排序(以正序排序为例)

(1)函数定义

int sort_list(list_t *my_list);;

选择排序思路

(2)注意点
  1. 外层循环可以不比较最后一个元素
(3)代码实现
int sort_list(list_t *my_list){if(NULL==my_list||NULL==my_list->phead){return -1;}nd_t *p=my_list->phead;nd_t *q=NULL;while(p->next!=my_list->phead){q=p->next;while(q!=my_list->phead){if(p->data>q->data){int temp=p->data;p->data=q->data;q->data=temp;}q=q->next;}p=p->next;}return 0;
}

9.剔重

(1)函数定义

int dedup_list(list_t *my_list);

动静指针配合
选择排序思路

(2)注意点
  1. 此时外层循环使用p->next!=phead或者p!=phead均可,循环链表此刻不会报段错误,但是用第一种效率会相对略高
(3)代码实现
int dedup_list(list_t *my_list){//至少有一个元素if(NULL==my_list||NULL==my_list->phead){return -1;}nd_t *p=my_list->phead;nd_t *q=NULL;nd_t *m=NULL;while(p->next!=my_list->phead){m=p;q=p->next;while(q!=my_list->phead){if(p->data==q->data){m->next=q->next;free(q);q=m->next;}else{m=q;q=q->next;}}p=p->next;}
}

(四)应用:实现约瑟夫环

1.问题描述

有一位叫约瑟夫的将军,在一次战斗中,连同手下的士兵一起被俘虏了。手下的士兵都非常爱国,宁死不投降,约瑟夫将军想了个办法:
让大家站成一圈,开始数数,从1开始数,数到7的人就自杀,
下一个人重新从1开始数,数到7再自杀,依次类推
直到只剩下一个人为止,最终剩下的就是约瑟夫将军,
然后他不想死,他投降了。这种“圈”,我们称之为“约瑟夫环”

要求:编写代码,模拟约瑟夫环淘汰人的过程,
命令行输入 ./a.out 总人数 数到几自杀 (总人数>1 数到几自杀>1 )
要求程序输出:
第x次 淘汰的是y号
以及最终剩下的是几号
如:输入 ./a.out 5 3 则程序输出
第1次 淘汰的是3号
第2次 淘汰的是1号
第3次 淘汰的是5号
第4次 淘汰的是2号
最后剩下的是 4 号

2. 问题分析

首先需要检查参数的合理性,参数都是以字符串形式保存的,需要转换成int型数据;
无头链表创建链表时就是创建第一个节点,即编号为1的人,之后依次开始创建节点

3. 代码实现

#include <stdio.h>
#include <stdlib.h>typedef struct _Node{int data;struct _Node *next;
}node_t;node_t *create_circle(int num){//创建第一个节点node_t *phead=(node_t *)malloc(sizeof(node_t));if(NULL==phead) return NULL;phead->data=1;phead->next=phead;//创建剩余节点node_t *pnew=NULL;node_t *ptemp=phead;for(int i=1;i<num;i++){pnew=(node_t *)malloc(sizeof(node_t));pnew->data=i+1;if(NULL==pnew) return NULL;//找到尾节点while (ptemp->next!=phead)ptemp=ptemp->next;pnew->next=ptemp->next;ptemp->next=pnew;}return phead;
}int print_circle(node_t *phead){if(NULL==phead) return -1;node_t *ptemp=phead;while(ptemp->next!=phead){printf("%d ",ptemp->data);ptemp=ptemp->next;}printf("%d ",ptemp->data);putchar(10);return 0;
}int del_circle(node_t *phead,int count){if(NULL==phead) return -1;int c=1;int sum=0;node_t *pprev=NULL;while(phead->next!=phead){if(c==count){sum++;c=1;printf("第%d次淘汰%d号\n",sum,phead->data);pprev->next=phead->next;free(phead);phead=pprev->next;continue;}c++;pprev=phead;phead=phead->next;}printf("第%d号存活\n",phead->data);return 0;
}int main(int argc, char const *argv[])
{if (argc!=3){printf("./a/out 总人数 数到几\n");return -1;}int sum=atoi(argv[1]); //人数 int num=atoi(argv[2]); //数到几node_t *my_list=NULL;my_list=create_circle(sum);print_circle(my_list);del_circle(my_list,num);return 0;
}

4. 使用前面的循环链表实现

main.c文件:

#include "circle_list.h"int del(nd_t *phead,int n);
int main(int argc, char const *argv[])
{if(3 != argc){printf("参数不合理\n");return -1;}int num=atoi(argv[1]); //保存个数int n=atoi(argv[2]);//数到几if(num<=0){printf("人数应当大于0\n");return-1;}list_t *my_list=NULL;//第一个人及其编号create_list(&my_list);//后面的人for(int i=1;i<=num;i++){if(insert_list_by_tail(my_list,i)){printf("插入失败\n");return -1;}}print_list(my_list);  del(my_list->phead,n);return 0;
}int del(nd_t *phead,int n)
{if(NULL==phead){printf("传参错误\n");return -1;}if(0>=n){printf("传参错误,n应当大于0\n");return -1;}int index=0;nd_t *pptemp=NULL;while(phead->next!=phead){for(int i=0;i<n-1;i++) //phead默认移到下一位了,故只需要再移动n-1次{pptemp=phead;phead=phead->next;}//此时phead是需要删除的节点,执行删除操作pptemp->next=phead->next; printf("第%d次删除%d\n",index+1,phead->data);free(phead);//删除完成后pead等于后一个节点phead=pptemp->next;index++;}printf("%d存活\n",phead->data);free(phead);phead=NULL;return 0;
}

二、代码源码已上传资源

链接:
C语言实现循环链表源码链接
C语言实现约瑟夫环源码链接

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

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

相关文章

【linux】运维-基础知识-认知hahoop周边

1. HDFS HDFS&#xff08;Hadoop Distributed File System&#xff09;–Hadoop分布式文件存储系统 源自于Google的GFS论文&#xff0c;HDFS是GFS的克隆版 HDFS是Hadoop中数据存储和管理的基础 他是一个高容错的系统&#xff0c;能够自动解决硬件故障&#xff0c;eg&#xff1a…

【Linux 网络编程】网络的背景、协议的分层知识!

文章目录 1. 计算机网络背景2. 认识 "协议"3. 协议分层 1. 计算机网络背景 网络互联: 多台计算机连接在一起, 完成数据共享; &#x1f34e;局域网&#xff08;LAN----Local Area Network&#xff09;: 计算机数量更多了, 通过交换机和路由器连接。 &#x1f34e; 广…

多模态模型入门:BLIP与OWL-ViT

BLIP 数据预处理 CapFilt&#xff1a;标题和过滤 由于多模态模型需要大量数据集&#xff0c;因此通常必须使用图像和替代文本 (alt-text) 对从互联网上抓取这些数据集。然而&#xff0c;替代文本通常不能准确描述图像的视觉内容&#xff0c;使其成为噪声信号&#xff0c;对于…

MAC M1 —— Install

文章目录 MAC M1 —— Install安装IDEA安装JDK安装Maven安装brew无法创建文件 /data/serverMac 修改终端用户名&#xff08;主机名&#xff09;PyCharm MAC M1 —— Install 安装IDEA 关键词&#xff1a;2020到2021.3的激活步骤。找下Download文件夹 安装JDK 在个人的电脑上…

《探索Stable Diffusion:AI绘画的创意之路与实战秘籍》

《Stable Diffusion AI 绘画从提示词到模型出图》介绍了 Stable Diffusion AI 绘画工具及其使用技巧。书中内容分为两部分&#xff1a;“基础操作篇”&#xff0c;讲解了 SD 文生图、图生图、提示词、模型、ControlNet 插件等核心技术的应用&#xff0c;帮助读者快速从新手成长…

java中,怎样用最简单方法实现写word文档

在跨平台环境中实现写word时&#xff0c;如果用现成的库&#xff0c;就会涉及跨平台兼容性问题&#xff0c;比如在安卓与java中实现写word的功能。还有一个问题就是&#xff0c;完全用程序生成word文档&#xff0c;工作量较大。所以采用了模板替换的方法。 docx文档本质就是一…

算法与数据结构:二叉排序树与AVL树

ACM大牛带你玩转算法与数据结构-课程资料 本笔记属于船说系列课程之一&#xff0c;课程链接&#xff1a; 哔哩哔哩_bilibilihttps://www.bilibili.com/cheese/play/ep66799?csourceprivate_space_class_null&spm_id_from333.999.0.0 你也可以选择购买『船说系列课程-年度会…

# AI作画原理:生成对抗网络(GAN)的原理与应用

AI作画原理&#xff1a;生成对抗网络&#xff08;GAN&#xff09;的原理与应用 现在&#xff0c;AI已经可以画出非常逼真的图像了。那么&#xff0c;AI是怎么做到这一点的呢&#xff1f; 深度学习与生成对抗网络&#xff08;GAN&#xff09; AI画画的核心技术之一是深度学习&…

关于MySQL数据库和数据表的基础

目录 一. 数据库的基础SQL 1. 创建数据库 2. 查看当前有哪些数据库 3. 选中数据库 4. 删除数据库 5. 小结 二. 数据表的基础SQL 1. 创建数据表 2. 查看当前数据库中有哪些表 3. 查看指定表的详细情况(查看表的结构) 4. 删除表 5. 小结 一. 数据库的基础SQL 1. 创建…

史上最全排序算法整理!(1)

1.排序的概念及其应用 1.1排序的概念 排序是计算机内经常进行的一种操作&#xff0c;其目的是将一组“无序”的记录序列调整为“有序”的记录序列。分内部排序和外部排序&#xff0c;若整个排序过程不需要访问外存便能完成&#xff0c;则称此类排序问题为内部排序。反之&#…

实战解析:爬取音乐每日推荐歌单并自动分享

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、准备阶段 三、实战步骤 四、总结与展望 一、引言 在数字化时代&#xff0c…

Gartner发布评估威胁情报计划有效性指南:评估威胁情报有效性的四个步骤

许多组织都在努力实施 TI 并评估其价值。安全和风险管理领导者必须使用优先情报要求来评估其 TI 计划的有效性&#xff0c;并根据其组织战略完善该计划。 主要发现 尽管许多组织已将威胁情报 (TI) 纳入其安全计划&#xff0c;但他们很难评估其性能、成熟度以及在相关产品和服务…

糖尿病视网膜病变分级新方法:卷积网络做分割和诊断 + 大模型生成详细的测试和治疗建议

糖尿病视网膜病变分级新方法&#xff1a;卷积网络做分割和诊断 大模型生成详细的测试和治疗建议 提出背景相关工作3.1 数据集3.1.1 病变分割 3.1.2 图像分级3.1.3 大型语言模型&#xff08;LLMs&#xff09; 解法 数据预处理 数据增强 网络架构 训练过程 测试过程子解法1…

【408真题】2009-25

“接”是针对题目进行必要的分析&#xff0c;比较简略&#xff1b; “化”是对题目中所涉及到的知识点进行详细解释&#xff1b; “发”是对此题型的解题套路总结&#xff0c;并结合历年真题或者典型例题进行运用。 涉及到的知识全部来源于王道各科教材&#xff08;2025版&…

【数据结构与算法 | 队列篇】力扣102, 107

1. 力扣102 : 二叉树的层序遍历 (1). 题 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3]…

STM32FLASH闪存

文章目录 前言首先来回顾一下存储器映像FLASH简介闪存模块组织Flash基本结构&#xff08;关系&#xff09;图Flash解锁使用指针访问存储器FLASH操作Flash全擦除Flash页擦除Flash写入 选项字节选项字节操作选项字节擦除选项字节写入 器件电子签名注意闪存控制寄存器一览 前言 本…

[leetcode hot 150]第一百九十一题,位1的个数

题目&#xff1a; 编写一个函数&#xff0c;输入是一个无符号整数&#xff08;以二进制串的形式&#xff09;&#xff0c;返回其二进制表达式中设置位的个数&#xff08;也被称为汉明重量&#xff09;。 这道题比较简单&#xff0c;直接对最后一位进行与1的与操作&#xff0c;然…

RTPS协议之Messages Module

目录 Messages ModuleType定义RTPS消息结构RTPS消息头子消息结构 RTPS消息接收者SubmessageElementsRTPS HeaderRTPS Submessages Messages Module RTPS Writer和RTPS Reader之间的交换数据的消息。 Type定义 TypePurposeProtocolId_tSubmessageFlagsub msg flagSubmessageK…

第16章-超声波跟随功能 基于STM32的三路超声波自动跟随小车 毕业设计 课程设计

第16章-超声波跟随功能 无PID跟随功能 //超声波跟随if(HC_SR04_Read() > 25){motorForward();//前进HAL_Delay(100);}if(HC_SR04_Read() < 20){motorBackward();//后退HAL_Delay(100);}PID跟随功能 在pid.c中定义一组PID参数 tPid pidFollow; //定距离跟随PIDpidFol…

越来越多的连锁企业选择开源连锁收银系统

连锁企业的收银系统作为其信息化的基础&#xff0c;随着运营的复杂化&#xff0c;越来越多的连锁企业选择开源连锁收银系统来满足其日常经营需要。商淘云为大家分享连锁企业选择开源连锁收银系统的三大原因&#xff0c;大家点赞收藏。 首先是灵活性和定制性强&#xff0c;连锁企…