选课清单--数据结构课程设计(十字链表+哈希表实现)

题目如上(九院版,被老师要求选这个题目做,不知道还有没有别的学校是这种题目,都可以相互借鉴hh)

代码写的有冗余,结构体应该有三个,一个学生,一个课程,一个十字链表的结构体,如果公用十字链表的结构体,学生和课程会有很多指针用不上,但是我懒,不想改了,将就着看吧......

代码如下:

//课程编号为1——2500的编号 
//学号为十位数字 
#include<cstdio>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<time.h> 
#include<map>
using namespace std;
const int MAXstu=40010,MAXcou=2510,mod=1e5;
typedef long long LL;
bool st1[MAXstu];
bool st2[MAXcou];

//初始化学生和课程的姓名,方便生成整套的大数据
char stuNames[10][20]={"Alice","Bob","Charlie","David","Emma","Frank","Grace","Henry","Ivy","Jack"};
char couNames[10][20]={"Math","Physics","Chemistry","Biology","History","Literature","Art","Music","Computer Science","Geography"};


struct Node
{
	LL stuid;//学生学号
	char stuname[20];//学生姓名
	int couid;//课程编号
	char couname[20];//课程名
	struct Node *prestu;//指向学生前驱节点
	struct Node *stu;//指向学生后继节点
	struct Node *precou;//指向课程前驱节点
	struct Node *cou;//指向课程后继节点
};
struct Node students[MAXstu],courses[MAXcou]; 

//函数声明 
void Add_Stu();//添加学生 
void Add_Cou();//添加课程
void ChooseCourse();//学生进行选课
void printStuCou();//输出学生所选课程信息
void printCouStu();//输出课程被学生选的信息 
void DeleteStu();//删除学生信息 
void DeleteCou();//删除课程信息
int hash1(long long);//学生学号哈希 


LL hashid[MAXstu]={0};
int hash1(LL id){//学生学号哈希,采用除留余数法
	int k=id%MAXstu;
	while(hashid[k]!=id&&hashid[k]!=0){//线性探测
		k++;
		if(k==MAXstu)k=0;//循环数组
	}
	hashid[k]==id;
	return k;
}
void Add_Stu(char name[],LL id)//添加学生
{
	int k=hash1(id);//学号的哈希值
	if(st1[k]){
		printf("该学生已存在,请勿重复添加!!!\n");
		return;
	}
	st1[k]=true;
	strcpy(students[k].stuname,name);//姓名放里面
	students[k].stuid=id;//学号放里面
	students[k].cou=NULL;//该学生选的课程链表初始化为空
	students[k].precou=NULL; 
	printf("添加学生成功!!!\n"); 
}
void Add_Cou(char name[],int id)//添加课程
{
	if(st2[id]){
		printf("该课程已存在,请勿重复添加!!!\n");
		return;
	}
	st2[id]=true;
	strcpy(courses[id].couname,name);//课程名
	courses[id].couid=id;//课程编号
	courses[id].stu=NULL;//选该课程的学生链表初始化为空
	courses[id].prestu=NULL;
	printf("添加课程成功!!!\n");
}
void ChooseCourse(LL stuid,int couid)//学生进行选课
{
	Node *t=(Node*)malloc(sizeof(Node));//申请一个新的节点 
	t->stuid=stuid,t->couid=couid;
	strcpy(t->couname,courses[t->couid].couname);//课程名 
	
	//四个指针域都为空 
	t->cou=NULL;
	t->precou=NULL;
	t->stu=NULL;
	t->prestu=NULL;
	
	int k=hash1(t->stuid);//学号的哈希值 
	if(!st1[k])
	{
		printf("该学生不存在,输入错误,选课失败!!!\n"); 
		return;
	}
	if(!st2[t->couid])
	{
		printf("该课程不存在,输入错误,选课失败!!!\n");
		return;
	}
	strcpy(t->stuname,students[k].stuname);//学生姓名 
	//给学生连节点
	Node *p=students[k].cou;
	Node *q;
	if(p==NULL){
		students[k].cou=t;
	}else{
		q=p,p=p->cou;
		while(p!=NULL)q=p,p=p->cou;
		q->cou=t;
		t->precou=q;
	}
	
	//给课程连节点
	p=courses[t->couid].stu;
	if(p==NULL){
		courses[t->couid].stu=t;
	}else{
		q=p,p=p->stu;
		while(p!=NULL)q=p,p=p->stu;
		q->stu=t;
		t->prestu=q;
	}
	printf("学号为%010lld的学生成功选择了课程编号为%d的课程!!!\n",t->stuid,t->couid);
}


void printStuCou()//输出学生所选课程信息
{
	LL id;
	printf("请输入您要查找学生的学号:"); 
	scanf("%lld",&id);
	int k=hash1(id);
	if(!st1[k])
	{
		cout<<"该学生不存在,输入错误!!!"<<endl;
		return;
	}
	Node *p=students[k].cou;
	if(p==NULL){
		cout<<"该学生暂未选择任何课程!!!"<<endl;
		return;
	}
	printf("学生名为%s,学号为%010lld的学生所选的课程如下:\n",students[k].stuname,id);
	while(p!=NULL)
	{
		printf("课程编号:%04d   课程名:%s\n",p->couid,p->couname);
		p=p->cou;
	}
}
void printCouStu()//输出课程被学生选的信息 
{
	int id;
	printf("请输入您要查找的课程编号:");
	scanf("%d",&id);
	if(!st2[id])
	{
		cout<<"该课程不存在,输入错误!!!"<<endl;
		return;
	}
	Node *p=courses[id].stu;
	if(p==NULL){
		cout<<"该课程暂未被任何学生选择!!!"<<endl; 
		return;
	}
	printf("课程名为%s,课程编号为%d的课程被选的信息如下:\n",courses[id].couname,id);
	while(p!=NULL)
	{
		printf("学号:%010lld  学生姓名:%s\n",p->stuid,p->stuname);
		p=p->stu; 
	}
} 
void DeleteStu()//删除学生信息 
{
	LL id;
	printf("请输入您要删除的学生学号:");
	scanf("%lld",&id);
	int k=hash1(id);
	if(!st1[k])
	{
		printf("该学生不存在,删除失败!!!\n");
		return;
	} 
	st1[k]=false;//标记删除 
	Node *p=students[k].cou;
	while(p!=NULL)
	{
		if(p==courses[p->couid].stu)courses[p->couid].stu=p->stu;
		else{
			if(p->prestu!=NULL)p->prestu->stu=p->stu;
			if(p->stu!=NULL)p->stu->prestu=p->prestu;
		}
		Node *t=p;
		p=p->cou;
		delete(t);
	}
	printf("学号为%010lld的学生删除成功!!!\n",id); 
}

void DeleteCou()//删除课程信息
{
	int id;
	printf("请输入你要删除的课程编号:");
	scanf("%d",&id);
	if(!st2[id])
	{
		printf("不存在该课程,删除失败!!!\n");
		return;
	}
	st2[id]=false;//标记删除
	Node *p=courses[id].stu;
	while(p!=NULL)
	{
		int k=hash1(p->stuid);
		if(p==students[k].cou)students[k].cou=p->cou;
		else{
			if(p->precou!=NULL)p->precou->cou=p->cou;
			if(p->cou!=NULL)p->cou->precou=p->precou;
		}
		Node *t=p;
		p=p->stu;
		delete(t);
	}
	printf("课程编号为%d的课程删除成功!!!\n",id);
}

void initializeData()//初始化,随机生成学生和课程及学生选课的数据 
{
    srand(time(NULL));// 设置随机种子
    
    //生成随机学生数据,rand()最大可生成32767,9999999999/32767=305185 
    for (int i=0;i<MAXstu;++i)
	{
        LL id=(LL)305185*rand()%9999999999+1; // 随机生成学生学号
        char name[20];
		strcpy(name,stuNames[rand()%10]); // 从学生姓名数组中随机选择一个姓名
        Add_Stu(name,id);//添加学生
    }
    // 生成随机课程数据
    for (int i=0;i<MAXcou;i++)
	{
        int id=rand()%2500+1;//随机生成课程编号
		char name[20];
		strcpy(name,couNames[rand()%10]);
        Add_Cou(name,id);//添加课程 
    }
    
    //随机选择部分学生并为其分配已选的课程
    for (int i=0;i<MAXstu/2;i++)//假设有一半的学生已经完成选课 
	{
        int k=rand()%40000+1; //随机选择学生学号的哈希值 
        if(!st1[k])continue;//如果该学生不存在,则直接进入下层循环 
		LL stuid=students[k].stuid;//记录学生编号 
		
        int numCourses=rand()%5+1; //随机生成已选课程的数量,假设每个学生选 1 到 5 门课
        for(int j=0;j<numCourses;j++){
            int couid=rand()%2500+1; // 随机生成课程编号
            ChooseCourse(stuid,couid);//学生选课
        }
    }
}

int main()
{
	//initializeData();//初始化数据,不加这句话就要自己手动初始化了
	while(1)
	{
		cout<<"********************************"<<endl;
		cout<<"*====请选择以下数字进行操作====*"<<endl;
		cout<<"*     0 退出系统               *"<<endl;
		cout<<"*     1 添加学生信息           *"<<endl;
		cout<<"*     2 添加课程信息           *"<<endl;
		cout<<"*     3 删除学生信息           *"<<endl;
		cout<<"*     4 删除课程信息           *"<<endl;
		cout<<"*     5 学生进行选课           *"<<endl;
		cout<<"*     6 输出课程所选学生名单   *"<<endl;
		cout<<"*     7 输出学生选课课程清单   *"<<endl;
		cout<<"********************************"<<endl;
		int choice;
		printf("请输入您要做的操作:");
		scanf("%d",&choice);
		switch(choice)
		{
			case 0:exit(0);
			case 1:{
				int op=1;
				while(op){
					char name[20];
					LL id;
					printf("请输入要添加的学生姓名和学号(学号小于等于十位数):");
					scanf("%s%lld",name,&id);
					Add_Stu(name,id);
					printf("继续添加学生请输入1,否则输出0,请输入:");
					scanf("%d",&op);
				}
				break;
			}
			case 2:{
				int op=1;
				while(op){
					int id;
					char name[20];
					printf("请输入要添加的课程编号(课程编号小于等于四位数)和课程名:");
					scanf("%d%s",&id,name);
					Add_Cou(name,id);
					printf("继续添加课程请输入1,否则输出0,请输入:");
					scanf("%d",&op);
				}
				break;
			}
			case 3:DeleteStu();break;
			case 4:DeleteCou();break;
			case 5:{
				int op=1;
				while(op){
					LL stuid;
					int couid;
					scanf("%lld%d",&stuid,&couid);
					ChooseCourse(stuid,couid);
					printf("继续选课请输入1,否则输出0,请输入:"); 
					scanf("%d",&op);
				}
				break;
			}
			case 6:printCouStu();break;
			case 7:printStuCou();break;
		}
	}
	return 0;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值