#ifndef _SYSTEM_H_
#define _SYSTEM_H_
#include
#include
#include
#define SIZE 20000
using namespace std;
enum bugvalue
{
NULL_ERROR = -4,
MALLOC_ERROR,
NOT_FOUND,
ERROR,
TRUE,
};
typedef struct train
{
char trainNumber[50];
char departureStation[50];
char arrivalStation[50];
char departureTime[10];
char arrivalTime[10];
double price;
int seatCount;
}data_type;
typedef struct hash_node
{
data_type data;//数据
struct hash_node* next;//结点,相同键用链式存储
}hashnode, * hashnodep;
typedef struct Hash
{
hashnode* hash[SIZE];//哈希表的大小或者槽位数量
}Hash, * Hashp;
Hashp creat(void);
void menu(void);
int addp(Hashp p, data_type a);
int find(Hashp p, data_type* pdata);
int outt(Hashp p);
int del(Hashp p, data_type* pdata);
int destory(Hashp* p);
int hashcul(int hdata);
int save(Hashp p);
hashnodep savecreat(void);
int change(Hashp p, data_type pdata);
int login(void);
#endif
如何解决下标冲突:
写结构体时加入next指针,相同key值进行横向链表式存储
.cpp代码:
#define _CRT_SECURE_NO_WARNINGS
#include"t.h"
#include"string.h"
#include
#include
#include
using namespace std;
Hashp creat(void)
{
Hashp p = (Hashp)malloc(sizeof(Hash));//为新的哈希表分配空间
if (NULL == p)//分析是否成功分配
{
printf("malloc error\n");
return NULL;
}
memset(p, 0, sizeof(Hash));//新分配的内存块设置为0,所有字段初始化
return p;
}
int hashcul(int hdata)//将给定的整数转化为哈希值,将键转换为哈希值索引
{
return hdata / 1000 + hdata % 1000 - 20221;
}//key函数
int time(Hashp p, data_type pdata)
{
int i;
clock_t start, end;
double duration;
start = clock();
for (i = 0; i < 10000; i++) {
sprintf(pdata.trainNumber, "%d", i + 1);
sprintf(pdata.departureStation, "Departure%d", i + 1);
sprintf(pdata.arrivalStation, "Arrival%d", i + 1);
sprintf(pdata.departureTime, "09:00");
sprintf(pdata.arrivalTime, "11:00");
pdata.price = 100.0;
pdata.seatCount = 100;
addp(p, pdata);
}
end = clock();
duration = (double)(end - start) / CLOCKS_PER_SEC;
printf("一共进行了10000次数据添加,运行时间:%f秒\n", duration);
return 0;
}
int addp(Hashp p, data_type a)
{
if (NULL == p)//判断传入的哈希表是否有效
{
printf("NULL_ERROR\n");
return NULL_ERROR;
}
hashnodep pnode = (hashnodep)malloc(sizeof(hashnode));//为新的哈希节点动态分配内存
if (NULL == pnode)
{
printf("MALLOC_ERROR\n");
return MALLOC_ERROR;
}
pnode->data = a;//将传入的数据a赋值给新节点的数据字段
int id = atoi(pnode->data.trainNumber);//车次号转化为整数,确定结点存放在哈希表的位置
pnode->next = p->hash[id];//新节点的next指针设置为当前哈希表中相同索引的位置
p->hash[id] = pnode;
return TRUE;
}
int del(Hashp p, data_type* pdata)
{
if (NULL == p)
{
printf("NULL_ERROR\n");
return NULL_ERROR;
}
int id = atoi(pdata->trainNumber);
hashnodep pt = p->hash[id];//根据索引找到相应的结点
if (NULL == pt)
{
return NOT_FOUND;
}
if (0 == strcmp(pdata->trainNumber, pt->data.trainNumber))//再次对比找到的结点和要删除的索引是否相同
{
p->hash[id] = pt->next;//对应索引的结点设置为下一个结点,达到删除效果
strcpy(pdata->departureStation, pt->data.departureStation);
//将删除节点数据保存到pdata中
strcpy(pdata->arrivalStation, pt->data.arrivalStation);
strcpy(pdata->departureTime, pt->data.departureTime);
strcpy(pdata->arrivalTime, pt->data.arrivalTime);
pdata->price = pt->data.price;
pdata->seatCount = pt->data.seatCount;
free(pt);//释放以删除结点内存
pt = NULL;
}
return TRUE;
}
int change(Hashp p, data_type pdata)
{
if (NULL == p)
{
printf("NULL_ERROR\n");
return NULL_ERROR;
}
if (atoi(pdata.trainNumber) < 0)
{
printf("输入的车次不存在\n");
return NOT_FOUND;
}
int id = atoi(pdata.trainNumber);
hashnodep pt = p->hash[id];//通过索引找到对应结点,结点和车次代表不同,结点是哈希函数生成,然后通过结点遍历该节点的链表,找到匹配的车次
if (NULL == pt)
{
printf("NOT_FOUND\n");
return NOT_FOUND;
}
else
{
while (pt != NULL)
{
if (0 == strcmp(pt->data.trainNumber, pdata.trainNumber))
{
printf("要修改的车次信息为:起点:%s\t终点:%s\t出发时间:%s\t到达时间:%s\t价格:%.1f\t座位数量:%d\n", pt->data.departureStation, pt->data.arrivalStation, pt->data.departureTime, pt->data.arrivalTime, pt->data.price, pt->data.seatCount);
printf("修改新车次的 序号 起点 终点 出发时间 到达时间 价格 座位数量\n");
int sca = scanf("%s %s %s %s %s %lf %d", &pdata.trainNumber, &pdata.departureStation, &pdata.arrivalStation, &pdata.departureTime, &pdata.arrivalTime, &pdata.price, &pdata.seatCount);
if (sca != 7)
{
printf("输入格式错误!\n");
return ERROR;
}
strcpy(pt->data.trainNumber, pdata.trainNumber);
strcpy(pt->data.departureStation, pdata.departureStation);
strcpy(pt->data.arrivalStation, pdata.arrivalStation);
strcpy(pt->data.departureTime, pdata.departureTime);
strcpy(pt->data.arrivalTime, pdata.arrivalTime);
pt->data.price = pdata.price;
pt->data.seatCount = pdata.seatCount;
}
pt = pt->next;//遍历该节点的链表
}
}
return TRUE;
}
int find(Hashp p,string a1,string a2)
{
int count = 0;
if (NULL == p)
{
printf("NULL_ERROR\n");
return NULL_ERROR;
}
for (int i = 0; i < SIZE; i++)
{
if (NULL == p->hash[i])
{
continue;
}
hashnodep pt = p->hash[i];
while (NULL != pt)
{
if (0 == strcmp(pt->data.departureStation, a1.c_str()) && (0 == strcmp(pt->data.arrivalStation, a2.c_str())))
{
printf("车次:%s\t起点:%s\t终点:%s\t出发时间:%s\t到达时间:%s\t价格:%1f\t座位数量:%d\n", pt->data.trainNumber, pt->data.departureStation, pt->data.arrivalStation, pt->data.departureTime, pt->data.arrivalTime, pt->data.price, pt->data.seatCount);
count++;
}
pt = pt->next;
}
}
if (count == 0)
{
printf("未找到符合条件车次。");
}
printf("**************************************************\n");
return TRUE;
}
//显示表
int outt(Hashp p)
{
if (NULL == p)
{
printf("NULL_ERROR\n");
return NULL_ERROR;
}
for (int i = 0; i < SIZE; i++)//这个循环是遍历哈希表的每个槽位
{
if (NULL == p->hash[i])
{
continue;
}
hashnodep pt = p->hash[i];//指向当前的第一个节点
while (NULL != pt)//循环当前槽位中的链表
{
printf("车次:%s\t起点:%s\t终点:%s\t出发时间:%s\t到达时间:%s\t价格:%.1f\t座位数量:%d\n", pt->data.trainNumber, pt->data.departureStation, pt->data.arrivalStation, pt->data.departureTime, pt->data.arrivalTime, pt->data.price, pt->data.seatCount);
pt = pt->next;
}
printf("*********************************************************\n");
}
return TRUE;
}
int destory(Hashp* p)
{
if (NULL == *p)
{
printf("NULL_ERROR\n");
return NULL_ERROR;
}
for (int i = 0; i < SIZE; i++)
{
if (NULL == (*p)->hash[i])
{
continue;
}
hashnodep pdel = (*p)->hash[i];
while (pdel != NULL)
{
(*p)->hash[i] = pdel->next;
free(pdel);//释放结点内存
pdel = (*p)->hash[i];
}
}
free(*p);//释放哈希表结构体
*p = NULL;
return 0;
}
void mainMenu() {
std::cout << "===== 火车票订票管理系统菜单 =====\n";
std::cout << "1. 添加车次(管理员)\n";
std::cout << "2. 编辑已有车次(管理员)\n";
std::cout << "3. 查询所有车次信息\n";
std::cout << "4. 购票\n";
std::cout << "5. 退票\n";
std::cout << "6. 改签\n";
std::cout << "7. 查询车票\n";
std::cout << "8. 创建哈希表\n";
std::cout << "9. 摧毁哈希表\n";
std::cout << "10. 性能显示\n";
std::cout << "请输入您的选择: ";
}
int login(void)
{
printf("********火车票订票管理系统*******\n");
printf("*********欢迎使用,请登录**********\n");
printf("1*****************************登录\n");
printf("2*****************************退出\n");
printf("**********************************\n");
printf("请选择功能:");
int menu = 0;
if (1 != scanf("%d", &menu))
{
printf("输入格式不正确 致命错误\n");
return 0;
}
char s[10] = { 0 };
char s1[10] = { 0 };
switch (menu)
{
case 1:
printf("输入用户名及密码\n");
scanf("%s%*c%s", s, s1);
if (!strcmp("admin", s) && !strcmp("123", s1))
{
printf("Welcome! administrator!\n");
return 1;
}
else if (!strcmp("stu", s) && !strcmp("456", s1))
{
printf("Welcome! stu\n");
return 2;
}
else
{
printf("用户名或密码错误 请重新输入\n\n");
login();
break;
}
default:
{printf("程序已退出\n");
return 0;
}}
return 0;
}
int exchange(Hashp p, string a, string b)
{
int count = 0; double amount; double money;
if (NULL == p)
{
printf("NULL_ERROR\n");
return NULL_ERROR;
}
for (int i = 0; i < SIZE; i++)
{
if (NULL == p->hash[i])
{
continue;
}
hashnodep pt = p->hash[i];
while (NULL != pt)
{
if (0 == strcmp(pt->data.trainNumber, a.c_str()))
{
pt->data.seatCount++;
amount = pt->data.price;
count++;
}
else if (0 == strcmp(pt->data.trainNumber, b.c_str()))
{
pt->data.seatCount--;
money = pt->data.price;
count++;
}
pt = pt->next;
}
}
double a1 = money - amount; double x = 0;
double a2 = amount - money;
if (a1 > 0)
{
printf("请支付%lf元\n", a1);
scanf("%lf", &x);
if (a1 == x)
printf("支付成功");
}
else
{
printf("已退回%lf元", a2);
}
printf("**************************************************\n");
return TRUE;
}
int refund(Hashp p, string a)
{
int count = 0; double amount; double money;
if (NULL == p)
{
printf("NULL_ERROR\n");
return NULL_ERROR;
}
for (int i = 0; i < SIZE; i++)
{
if (NULL == p->hash[i])
{
continue;
}
hashnodep pt = p->hash[i];
while (NULL != pt)
{
if (0 == strcmp(pt->data.trainNumber, a.c_str()))
{
printf("已退回:%1f元\n", pt->data.price);
pt->data.seatCount++;
count++;
}
pt = pt->next;
}
if (count == 0)
{
printf("车次输入有误。");
}
}
printf("**************************************************\n");
return TRUE;
}
int payTicket(Hashp p,string a)
{
int count = 0; double amount; double money;
if (NULL == p)
{
printf("NULL_ERROR\n");
return NULL_ERROR;
}
for (int i = 0; i < SIZE; i++)
{
if (NULL == p->hash[i])
{
continue;
}
hashnodep pt = p->hash[i];
while (NULL != pt)
{
if (0 == strcmp(pt->data.trainNumber, a.c_str()) )
{
printf("请支付:%1f\n", pt->data.price);
amount = pt->data.price;
pt->data.seatCount--;
count++;
}
pt = pt->next;
}
}
if (count == 0)
{
printf("车次输入有误。");
}
scanf("%lf", &money);
if (money == amount)
printf("支付成功!");
else
printf("输入金额有误");
printf("**************************************************\n");
return TRUE;
}
int main()
{int user = login();
int me = 0; int mod = 0; int ad = 0;
char n[20];
data_type cdata = {0};
Hashp ph = NULL;
char s1[20]; char s2[20];
while (1)
{
mainMenu();
printf("选择以上功能的一种:");
scanf("%d", &me);
switch (me)
{case 1:
{ printf("\n");
printf("********Mode selection********\n");
printf("1*********************输入车次\n");
printf("2*************************取消\n");
printf("******************************\n");
printf("选择输入模式:");
if (1 != scanf("%d", &mod))
{
printf("输入格式不正确\n");
return ERROR;
}
switch (mod)
{case 1:
{if (2 == user)
{printf("没有访问权限");break;
}
printf("输入添加车次的 序号 起点 终点 出发时间 到达时间 价格 座位数量\n");
if (7 != scanf("%49s %49s %49s %49s %49s %lf %d", cdata.trainNumber, cdata.departureStation, cdata.arrivalStation, cdata.departureTime, cdata.arrivalTime, &cdata.price, &cdata.seatCount))
{printf("车次信息不完整\n");
}
ad = addp(ph, cdata);
if (ad < 0)
{printf("ERROR\n\n");}
else
{printf("添加成功!\n\n");}
case 3:
printf("\n");
}
}
break;
case 2:
{
if (2 == user)
{
printf("你的权限不足 无法操作\n\n");
break;
}
int mod = 0;
printf("\n");
printf("********Mode selection********\n");
printf("1*********************修改车次信息\n");
printf("2*********************删除车次信息\n");
printf("3*************************取消\n");
printf("******************************\n");
printf("选择操作模式:");
scanf("%d", &mod);
switch (mod)
{
case 1:
{printf("请输入需要修改的车次。");
scanf("%s", cdata.trainNumber);
int de = change(ph, cdata);
if (de < 0)
{
printf("ERROR\n\n");
}
else if (de == NOT_FOUND)
{
printf("该车次不存在\n\n");
}
else
{
printf("修改成功\n\n");
}
break;
}
case 2:
{
int de = del(ph, &cdata);
if (NOT_FOUND == de)
{
printf("该车次不存在\n\n");
}
else if (de < 0)
{
printf("ERROR\n\n");
}
else
{
printf("删除成功\n\n");
}
break;
}
case 3:
{
printf("\n");
}
}
break;
}
case 3:
{
int out = outt(ph);
if (out < 0)
{
printf("ERROR\n\n");
}
else
printf("输出完成\n\n");
break;
}
case 4: {
printf("输入你所要支付的车次:");
scanf("%s", &n);
payTicket(ph,n); }
break;
case 5: {
printf("请输入退订车次:");
scanf("%s", s1);
refund(ph, s1);
}
break;
case 6:
{
printf("请输入改签车次:");
scanf("%s", s1);
printf("请输入新车次:");
scanf("%s", s2);
exchange(ph, s1, s2);
}
break;
case 7: {
printf("请输入出发点:");scanf("%s", s1);
printf("请输入终点:");scanf("%s", s2);
find(ph, s1, s2);
}
break;
case 9:
{
destory(&ph);
printf("程序已退出\n");
return TRUE;}
case 8:
{ph = creat();
if (NULL == ph)
{
printf("NULL_ERROR\n");
}
else
{
printf("创建哈希表成功\n\n");
}
}break;
case 10:
time(ph, cdata);
break;
}}
}return 0;
}
效果图: