ZZULI-新冠疫苗接种信息管理系统

✅简介:与大家一起加油,希望文章能够帮助各位!!!!
保持学习、保持热爱、认真分享、一起进步!!!

 

目录

✅简介:与大家一起加油,希望文章能够帮助各位!!!!

保持学习、保持热爱、认真分享、一起进步!!!

 

试验任务:

数据结构的定义:

 1.逐个显示信息表中疫苗接种的信息

2. 输出目前满足接种第二剂疫苗的接种者信息 

3. 给定一个新增接种者的信息,插入到表中指定的位置

4. 删除指定位置

5. 利用直接插入排序或者折半插入排序按照身份证号进行排序(升序排序)

6. 利用快速排序和堆排序按照第一剂接种的时间进行排序

7. 根据身份证号进行折半查找,若查找成功,则返回此接种者的信息

8. 给定接种者的身份证号或姓名,查找疫苗接种信息,并输出冲突次数和平均查找长度

效果展示:

完整代码放在附件里了,想要的自取哦!


试验任务:

设计并实现一个新冠疫苗接种信息管理系统(假设该系统面向需要接种两剂的疫苗)。要求定义一个包含接种者的身份证号、姓名、已接种了几剂疫苗、第一剂接种时间、第二剂接种时间等信息的顺序表,系统至少包含以下功能:

(1)逐个显示信息表中疫苗接种的信息;

(2)两剂疫苗接种需要间隔14~28天,输出目前满足接种第二剂疫苗的接种者信息;

(3)给定一个新增接种者的信息,插入到表中指定的位置;

(4)分别删除指定位置和给定接种者身份证号的接种者记录信息;

(5)利用直接插入排序或者折半插入排序按照身份证号进行排序;

(6)分别利用快速排序和堆排序按照第一剂接种的时间进行排序;

(7)根据身份证号进行折半查找,若查找成功,则返回此接种者的信息;

(9)为提高检索效率,要求利用利用接种者的姓氏为关键字建立哈希表,并利用链地址法处理冲突。给定接种者的身份证号或姓名,查找疫苗接种信息,并输出冲突次数和平均查找长度;

(10)提供用户菜单,方便选择执行功能。可以设计成一级或多级菜单。所有功能都可重复执行。

思路:

在定义数据元素的结构时,可以根据自己的需求去定义一个较好的数据结构。如果可以留一个哨兵的位置,在实现查找排序等的操作的时候会更加的方便。(这里我要说一下,写着的时候才想起来,那时候就不想修改了)。

各个小模块的设计,完成对应的要求。

数据结构的定义:

//头文件的引用
#include 
#include
#include
#include
#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.逐个显示信息表中疫苗接种的信息

// 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");	
	}
} 

效果展示:

2. 输出目前满足接种第二剂疫苗的接种者信息 

/*
注意: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"); 
		}
	}
}

效果展示:

ZZULI-新冠疫苗接种信息管理系统_第1张图片

3. 给定一个新增接种者的信息,插入到表中指定的位置

这里对第一次和第二次接种疫苗都有实现

// 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("数据输入错误!"); 
	}	
}

效果展示:

ZZULI-新冠疫苗接种信息管理系统_第2张图片

ZZULI-新冠疫苗接种信息管理系统_第3张图片

4. 删除指定位置

// 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"); 
	}
}

ZZULI-新冠疫苗接种信息管理系统_第4张图片

5. 利用直接插入排序或者折半插入排序按照身份证号进行排序(升序排序)

// 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;
        }
    }
}

效果展示:

6. 利用快速排序和堆排序按照第一剂接种的时间进行排序

/*
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. 根据身份证号进行折半查找,若查找成功,则返回此接种者的信息

// 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("查无此人!");
}

效果展示:

ZZULI-新冠疫苗接种信息管理系统_第5张图片

8. 给定接种者的身份证号或姓名,查找疫苗接种信息,并输出冲突次数和平均查找长度

// 哈希函数
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;ilen;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; 
	}
}
//查找操作放在主函数里了,其实应该封装成对应的方法

效果展示:

ZZULI-新冠疫苗接种信息管理系统_第6张图片

(主要原因:信息太少,没有产生冲突)

完整代码放在附件里了,想要的自取哦!

总结:

在设计哈希函数做映射的时候,考虑到计算机是UTF-8的编码格式,想能够去唯一对应汉字,所以需要的下标索引应该为0~ 65535。但是考虑到内存的大小,最终只保留高位的编码。UTF-8的编码格式如下:

对于大部分中文字符来说,其UTF-8编码占用三个字节。这三个字节的格式为:

1.   第一个字节以“1110xxxx”的形式开头,其中xxxx表示该中文字符的高4位二进制表示。

2.   第二个字节以“10xxxxxx”的形式开头,其中xxxxxx表示中间的6位二进制表示。

3.    第三个字节以“10xxxxxx”的形式开头,其中xxxxxx表示低6位二进制表示。

以上均是个人的理解,如果有不对的地方请各位大佬帮忙斧正!!

追光的人,终会光芒万丈!!

你可能感兴趣的:(数据结构,算法,数据结构,c#,哈希算法)