📄 哈希表学生管理系统.cpp
字号:
/*******************************************************************************
程序名称 : 哈希表学生管理系统
作者 : 040540227 张欢
单位 : 南京航空航天大学信息科学与技术学院
完成时间 : 2007年1月10号
程序功能 : 1.把学生的信息(姓名,学号)插到哈希表中。
2.按照姓名或学号查找学生。
3.删除某学生。
4.查看哈希表内容。
5.修改某学生的信息。
主要用的知识 : 哈希表存储方式,链地址解决冲突,函数调用,循环控制,字符串处理等等。
希望广大用户及时反馈意见以便我们为您提供更好的服务,谢谢!
********************************************************************************/
#include"stdio.h"
#include"conio.h"
#include"string.h"
#include"stdlib.h"
typedef struct student //学生结点
{
char name[16];
char number[11];
struct student *next;
}student;
/**************************************全局变量***********************************/
student *HashTable[16]; //数组里的16个值元素都是头指针(什么都不存),全局变量
char name[16];
char number[11];
int location; //地址
/*************************************哈希函数***********************************/
int Hash(char *str) //哈希函数
{
int i;
i = strlen(str);
return i;
}
/*********************************按姓名查找************************************/
student *search1(char *name) //按姓名查找的简单,因为可以用哈希函数
{
student *p;
location = Hash(name); //此同学应该存放的地址
p = HashTable[location];
while (p && strcmp(p->name,name)) //p指针不空并且p->name不是要找的那个name则循环进行
p = p->next;
if (!p)
return NULL; //返回空指针
else
return p; //返回指针p
}
/*********************************按学号查找************************************/
student *search2(char *number)
{
int i;
student *p,*q;
for(i = 0 ; i < 16 ; i++)
{
p = HashTable[i];
if (p == NULL) //该地址上没有元素的情况
continue; //p等于下一个位置上的指针
else if (p->next == NULL) //该地址上只有1个元素的情况
{
if (strcmp(p->number,number))
continue;
else
return p;
}
else //该地址上多于1个元素的情况
{
q = HashTable[i]; //此时p和q都是HashTable[i]
while (p && strcmp(p->number,number)) //p指针不空并且p->name不是要找的那个name则循环进行
{
q = p; //保持q在p的前面
p = p->next;
}
if (!p)
continue;
else //p指针所指的结点 p->name就是要查找的name
return p;
}
}
return NULL; //如果直到i=16时才结束,正常结束,则没有找到该学号的学生
}
/*******************************插入某指针指向的结点*****************************/
void ins(student *q)
{
location = strlen(q->name);
if (HashTable[location] == NULL) //此位置上还没有插入一个元素
{
HashTable[location] = q; // HashTable[location]指向node
q->next = NULL;
}
else //向前插
{
q->next = HashTable[location]; //HashTable[location] 是指针!!
HashTable[location] = q;
}
}
/*********************************删除p指针所指的结点****************************/
void del(student *p) //删除p指针所指向的结点
{
student *q;
int location = Hash(p->name); //找到地址
if (p->next == NULL) //要删除的元素所在地址上只有1个元素的情况
{
HashTable[location] = NULL;
free(p);
}
else //要删除的元素所在地址上多于1个元素的情况
{
p = HashTable[location];
q = HashTable[location];
while (p && strcmp(p->name,name)) //p指针不空并且p->name不是要找的那个name则循环进行
{
q = p; //保持q在p的前面
p = p->next;
}
//循环结束时已经找到要删的结点了
q->next = p->next;
free(p); //删除p结点
}
}
/************************************插入****************************************/
void Insert() //插入完成
{
student *node;
printf("请输入要插入的同学的姓名(汉语拼音,字符不多于15个):\n");
gets(name);
printf("请输入要插入的同学的学号(不多于10位):\n");
gets(number);
node = (student *)malloc(sizeof(struct student));
node->next = NULL;
strcpy(node->name,name); //复制字符串
strcpy(node->number,number);
location = Hash(node->name); //找到应该插入的位置
if (HashTable[location] == NULL) //此位置上还没有插入一个元素
{
HashTable[location] = node; // HashTable[location]指向node
printf(" 插入完成!\n\n");
}
else //向前插
{
node->next = HashTable[location]; //HashTable[location] 是指针!!
HashTable[location] = node;
printf(" 插入完成!\n\n");
}
}
void Delete() //按姓名删除
{
student *p;
char info[16];
printf("请输入要删除的同学的姓名或学号:\n");
gets(info);
if (info[0] >= '0' && info[0] <= '9') //知道输入的是学号
{
p = search2(info);
if(!p)
{
printf("没有此学号的学生,无法修改信息!\n\n");
return;
}
else
{
del(p);
printf("删除成功!\n\n");
return;
}
}
else
{
p = search1(info);
if (!p)
{
printf("没有此学号的学生,无法修改信息!\n\n");
return;
}
else
{
del(p);
printf("删除成功!\n\n");
return;
}
}
}
/**********************************输出哈希表全部的内容*******************************/
void print()
{
int i ;
student *p ;
printf("哈希表的所有元素及所在地址如下:\n");
for (i = 0 ; i < 16 ; i++)
{
printf("%-2d :",i);
if (!HashTable[i])
printf("\n"); //如果是空指针
else //输出该地址下所有的元素
{
for(p = HashTable[i] ; p ; p = p->next)
{
printf("%s",p->name); //姓名
printf("(%s)",p->number); //学号
if (p->next)
printf("--->");
}
printf("\n");
}
}
}
/******************************************修改内容**************************************/
void change() //虽然复杂,但是思想简单
{
char ch;
char info[16]; //可以放姓名可以放学号
char str[16];
char c;
int i;
student *p, *q;
printf("请输入你要更改信息的学生的姓名或学号:\n"); //这里我用了一个小技巧
gets(info);
if (info[0] >= '0' && info[0] <= '9') //知道输入的是学号
{
p = search2(info);
if (!p)
{
printf("没有此学号的学生,无法修改信息!\n\n");
return ;
}
else //要修改的人在哈希表中
{
i=strlen(p->name);
printf("你要修改姓名,还是学号?请选择1.姓名.2.学号.\n");
c = getch();
if (c == '1')
{
printf("\n此人姓名是:%s.请输入改变后的姓名(如果新名字长度和原来不一样,则此学生将要换到哈希表中的另一个位置上!):\n",p->name);
gets(str);
if (strlen(str)!=strlen(p->name))
{
q = (student *)malloc(sizeof(struct student));
//申请新的结点
strcpy(q->number,p->number); //学号保留到q上
del(p);
strcpy(q->name,str); //换上新名字,把q所指结点插入到合适的位置上
ins(q); //插入q所指的结点
printf("姓名更改完毕,该学生已经由原位置%d转移到位置%d上了!\n\n",i,strlen(q->name));
printf("\n");
}
else
{
strcpy(p->name,str); //新名字和原来一样长的
printf("姓名更改完毕!\n");
}
}
else //c==2修改学号
{
printf("此人学号是:%s.请输入改变后的学号:",p->number);
gets(str);
strcpy(p->number,str);
printf("学号更改完毕!\n");
}
}
}
else //知道输入的是姓名
{
p = search1(info);
if (!p)
{
printf("没有此姓名的学生,无法修改信息!\n\n");
return ;
}
else
{
i = strlen(p->name);
printf("你要修改姓名,还是学号?请选择1.姓名.2.学号.\n");
c = getch();
if (c == '1')
{
printf("\n此人姓名是:%s.请输入改变后的姓名(如果新名字长度和原来不一样,则此学生将要换到哈希表中的另一个位置上!):\n",p->name);
gets(str);
if (strlen(str)!=strlen(p->name))
{
q = (student *)malloc(sizeof(struct student));
//申请新的结点
strcpy(q->number,p->number); //学号保留到q上
del(p);
strcpy(q->name,str); //换上新名字,把q所指结点插入到合适的位置上
ins(q);
printf("姓名更改完毕,该学生已经由原位置%d转移到位置%d上了!\n\n",i,strlen(q->name));
printf("\n");
}
else
{
strcpy(p->name,str); //新名字和原来一样长的
printf("姓名更改完毕!\n\n");
}
}
else //c==2修改学号
{
printf("此人学号是:%s.请输入改变后的学号:",p->number);
gets(str);
strcpy(p->number,str);
printf("学号更改完毕!\n\n");
}
}
}
}
/**************************************两种方式查找**************************************/
void search() //先编查找,两种方式查找
{
char c;
printf("你是按姓名查找还是按学号查找?请选择:1.姓名. 2.学号.\n");
c = getch();
if (c == '1')
{
printf("请输入你要查找的人的姓名(不多于15个字符):\n");
gets(name);
printf("%s\n\n",search1(name)?"此人在哈希表中":"查无此人");
}
else if (c == '2')
{
printf("请输入你要查找的人的学号(不多于10个字符):\n");
gets(number);
printf("%s\n\n",search2(number)?"此人在哈希表中":"查无此人");
}
//search1,search2要带参数,便于传递
else
{
putch(7);
printf("你输入了'1','2'之外的字符,请检查!\n");
} //输入的选项有误则也返回NULL
}
void main()
{
char menu[220] = " 请选择你要的操作的序号:\n 1.插入元素\n 2.删除元素\n 3.查看哈希表\n 4.查找元素\n 5.更改信息\n 6.退出\n " ;
char c;
int i;
printf("\n\n");
printf(" ****************************************************************\n");
printf(" ** 程序说明:本程序利用哈希表,按照学生姓名(汉语拼音)长度分 **\n");
printf(" ** 配其所在地址,学生信息包括姓名,学号,可以对该表进行插入, **\n");
printf(" ** 删除,查找,查看,更改信息等操作,是一个管理学生的小系统 **\n");
printf(" ** ,若发现问题或有好的建议请及时反馈,以便我们为您提供更好 **\n");
printf(" ** 的服务! **\n");
printf(" ****************************************************************\n\n\n");
for(i = 0 ; i < 13 ; i++)
HashTable[i] = NULL; //初始置空
do
{
puts(menu);
c = getch();
putchar(c);
printf("\n\n");
switch (c)
{
case '1' : Insert();
break;
case '2' : Delete(); //两种方法的删除!!
break;
case '3' : print();
break;
case '4' : search(); //两种方法的查找!!
break;
case '5' : change(); //先查找,再修改
break;
case '6' : printf("谢谢使用本系统,欢迎再次使用!\n") ; //下面的while中退出!
break;
default :
putch(7) ;
printf("输入有误,请重新输入!\n") ;
}
}while(c!='6'); //while后面的';'不可少
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -