?? 哈希表學生管理系統.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 + -