?简介:与大家一起加油,希望文章能够帮助各位!!!!
💬保持学习、保持热爱、认真分享、一起进步!!!
目录
5. 利用直接插入排序或者折半插入排序按照身份证号进行排序(升序排序)
7. 根据身份证号进行折半查找,若查找成功,则返回此接种者的信息
8. 给定接种者的身份证号或姓名,查找疫苗接种信息,并输出冲突次数和平均查找长度
设计并实现一个新冠疫苗接种信息管理系统(假设该系统面向需要接种两剂的疫苗)。要求定义一个包含接种者的身份证号、姓名、已接种了几剂疫苗、第一剂接种时间、第二剂接种时间等信息的顺序表,系统至少包含以下功能:
(1)逐个显示信息表中疫苗接种的信息;
(2)两剂疫苗接种需要间隔14~28天,输出目前满足接种第二剂疫苗的接种者信息;
(3)给定一个新增接种者的信息,插入到表中指定的位置;
(4)分别删除指定位置和给定接种者身份证号的接种者记录信息;
(5)利用直接插入排序或者折半插入排序按照身份证号进行排序;
(6)分别利用快速排序和堆排序按照第一剂接种的时间进行排序;
(7)根据身份证号进行折半查找,若查找成功,则返回此接种者的信息;
(9)为提高检索效率,要求利用利用接种者的姓氏为关键字建立哈希表,并利用链地址法处理冲突。给定接种者的身份证号或姓名,查找疫苗接种信息,并输出冲突次数和平均查找长度;
(10)提供用户菜单,方便选择执行功能。可以设计成一级或多级菜单。所有功能都可重复执行。
思路:
在定义数据元素的结构时,可以根据自己的需求去定义一个较好的数据结构。如果可以留一个哨兵的位置,在实现查找排序等的操作的时候会更加的方便。(这里我要说一下,写着的时候才想起来,那时候就不想修改了)。
各个小模块的设计,完成对应的要求。
//头文件的引用
#include<stdio.h>
#include<stdbool.h>
#include<string.h>
#include<stdlib.h>
#define Max 999
#define hashSize 260
//定义一个存储时间类型的结构体
typedef struct _time{
int year;
int month;
int day;
// 0表示时间为NULL
int flag;
}time;
//接种信息
typedef struct _virusSystem{
char id[20];
char name[20];
int inoculumSize;
time oneTime;
time twoTime;
}virusSystem;
//顺序表
typedef struct _table{
virusSystem list[Max];
int len;
}table;
// 哈希表的桶结构体,使用链表处理冲突
typedef struct Node {
virusSystem data;
struct Node* next;
} Node;
// 哈希表结构体
typedef struct {
Node* buckets[hashSize]; // 存放链表头节点的数组
} HashTable;
// 1.显示疫苗接种信息
void tablePrint (table T) {
printf("\nid name inoculumSize oneTime twoTime \n");
printf("-------------------------------------------------------------------------------\n");
for (int i = 0; i < T.len; i++) {
printf("%s\t%s\t\t%d\t",T.list[i].id,T.list[i].name,T.list[i].inoculumSize);
timePrint(T.list[i].oneTime);
timePrint(T.list[i].twoTime);
printf("\n");
}
}
效果展示:
/*
注意:timePrint、timeAdd函数需要手动实现
timePrint:打印时间
timeAdd :返回两时间的差值,记得有闰年、平年的区别
*/
// 2.打印出满足时间间隔在 14~28天 接种人的信息
void enough (table T) {
printf("请输入当前时间:(PS: 年-月-日)\n");
time cur;
scanf("%d-%d-%d",&cur.year,&cur.month,&cur.day);
printf("\nid name inoculumSize oneTime twoTime \n");
printf("-------------------------------------------------------------------------------\n");
for (int i = 0; i < T.len; i++) {
if (timeAdd(T.list[i].oneTime,cur) >= 14 && timeAdd(T.list[i].oneTime,cur) <= 28 && T.list[i].twoTime.flag == 0 && T.list[i].oneTime.flag != 0) {
printf("%s\t%s\t\t%d\t",T.list[i].id,T.list[i].name,T.list[i].inoculumSize);
timePrint(T.list[i].oneTime);
timePrint(T.list[i].twoTime);
printf("\n");
}
}
}
效果展示:
这里对第一次和第二次接种疫苗都有实现
// 3.新增接种者信息
void insert (table* T) {
printf("请输入要插入的位置\n");
int n;
scanf("%d",&n);
for (int i = T->len; i >= n; i--)
T->list[i] = T->list[i-1];
printf("请输入接种者身份证号:\n");
scanf("%s",T->list[n-1].id);
printf("请输入接种者姓名:\n");
scanf("%s",T->list[n-1].name);
//增加表长
T->len++;
int m;
printf("接种者是第几次接种:PS(1 2)\n");
scanf("%d",&m);
switch (m){
case 1:
printf("请输入接种者第一次接种时间(PS:xxxx-xx-xx)\n");
scanf("%d-%d-%d",&T->list[n-1].oneTime.year,&T->list[n-1].oneTime.month,&T->list[n-1].oneTime.day);
T->list[n-1].oneTime.flag = 1;
T->list[n-1].twoTime.flag = 0;
break;
case 2:
printf("请输入接种者第一次接种时间(PS:xxxx-xx-xx)\n");
scanf("%d-%d-%d",&T->list[n-1].oneTime.year,&T->list[n-1].oneTime.month,&T->list[n-1].oneTime.day);
T->list[n-1].oneTime.flag = 1;
printf("请输入接种者第二次接种时间(PS:xxxx-xx-xx)\n");
scanf("%d-%d-%d",&T->list[n-1].twoTime.year,&T->list[n-1].twoTime.month,&T->list[n-1].twoTime.day);
T->list[n-1].twoTime.flag = 1;
break;
default :
T->list[n-1].inoculumSize = 0;
T->list[n-1].oneTime.flag = 0;
T->list[n-1].twoTime.flag = 0;
printf("数据输入错误!");
}
}
效果展示:
// 4.1根据位置删除接种者信息
void indexDelete (table* T,int n) {
if (n > T->len) {
printf("查无此人!\n");
return ;
}
for (int i = n - 1; i < T->len - 1; i++) {
T->list[i] = T->list[i+1];
}
T->len--;
}
// 4.2根据接种者身份证号删除接种者信息
void idDelete (table* T,char* s) {
int flag = 0;
for (int i = 0; i < T->len; i++) {
if (!strcmp(s,T->list[i].id)) {
flag = 1;
indexDelete(T,i+1);
}
}
if (flag == 0) {
printf("查无此人!\n");
}
}
// 5. 直接插入排序和折半插入排序一样主要都是找到要插入的位置
void straightSort(table* T) {
virusSystem temp;
for (int i = 1; i < T->len; i++) {
for (int j = i; j > 0 && atoll(T->list[j].id) < atoll(T->list[j-1].id); j--) {
temp = T->list[j];
T->list[j] = T->list[j-1];
T->list[j-1] = temp;
}
}
}
效果展示:
/*
compare函数需要自己实现,判断时间的大小
*/
int partition (table* T,int low,int high) {
virusSystem key = T->list[low];
while (low < high) {
while (low < high && compare(key.oneTime,T->list[high].oneTime)<=0)
--high;
T->list[low] = T->list[high];
while (low < high && compare(key.oneTime,T->list[low].oneTime)>=0)
++low;
T->list[high] = T->list[low];
}
T->list[low] = key;
return low;
}
void qSort (table* T,int low,int high) {
if (low < high) {
int pivotloc = partition(T,low,high);
qSort(T,low,pivotloc-1);
qSort(T,pivotloc+1,high);
}
}
效果展示:
// 7. 二分查找
void dichotomy (table* T,char* str) {
int low = 0,high = T->len-1;
int mid = (low + high) / 2;
while (low <= high) {
if (atoll(T->list[mid].id) == atoll(str)){
printf("\nid name inoculumSize oneTime twoTime \n");
printf("-------------------------------------------------------------------------------\n");
printf("%s\t%s\t\t%d\t",T->list[mid].id,T->list[mid].name,T->list[mid].inoculumSize);
timePrint(T->list[mid].oneTime);
timePrint(T->list[mid].twoTime);
printf("\n");
return ;
}
else if (atoll(T->list[mid].id) > atoll(str))
high = mid - 1;
else if (atoll(T->list[mid].id) < atoll(str))
low = mid + 1;
mid = (low + high) / 2;
}
printf("查无此人!");
}
效果展示:
// 哈希函数
unsigned int hashFunction (char* str) {
int n = (int)str[0];
n = n > -n ? n :-n;
return n;
}
// 初始化哈希表
void initHashTable(HashTable* hashTable) {
for (int i = 0; i < hashSize; i++) {
hashTable->buckets[i] = NULL; // 初始化为 NULL
}
}
//向哈希表中添加数据,采用头插法 (有虚拟头节点)
void insertIntoHashTable (HashTable* hash,table* T) {
initHashTable(hash);
for (int i=0;i<T->len;i++) {
Node* p = (Node*)malloc(sizeof(Node));
p->data = T->list[i];
p->next = hash->buckets[hashFunction(T->list[i].name)];
hash->buckets[hashFunction(T->list[i].name)] = p;
}
}
//查找操作放在主函数里了,其实应该封装成对应的方法
(主要原因:信息太少,没有产生冲突)
总结:
在设计哈希函数做映射的时候,考虑到计算机是UTF-8的编码格式,想能够去唯一对应汉字,所以需要的下标索引应该为0~ 65535。但是考虑到内存的大小,最终只保留高位的编码。UTF-8的编码格式如下:
对于大部分中文字符来说,其UTF-8编码占用三个字节。这三个字节的格式为:
1.?? 第一个字节以“1110xxxx”的形式开头,其中xxxx表示该中文字符的高4位二进制表示。
2.?? 第二个字节以“10xxxxxx”的形式开头,其中xxxxxx表示中间的6位二进制表示。
3.??? 第三个字节以“10xxxxxx”的形式开头,其中xxxxxx表示低6位二进制表示。
以上均是个人的理解,如果有不对的地方请各位大佬帮忙斧正!!
追光的人,终会光芒万丈!!