ch03.表栈队列--多重链表实现学生课程注册

ch03.表栈队列--多重链表实现学生课程注册

0.引言

多重链表的练习。

1.题目说明

一所有40000名学生和2500门课程的大学需要生成两种类型的报告。第一个报告列出每个班的注册者,第二个报告列出每个学生注册的班级。常用的实现方法是使用二维数组,这样一个数组将有1亿项。平均一个学生注册三门课程,因此实际上有意义的数据只有120000项,大约占0.1%。

在这里插入图片描述

数据结构定义:
在这里插入图片描述
在这里插入图片描述

用两个链表做索引,分别存储课程节点和学生节点,注册节点为多重链表。课程为固定的课程,先初始化好;然后从学生的角度进行注册。

整个数据结构的入口为CTList (Course Table List)STList (Student Table List)两个链表,多重链表的节点(注册上的节点)就是挂在这两个链表上的,遍历查询打印报告,分别输出这两个链表就是了!

2.代码实现

代码实现按照书中图片上进行注册。

#include <iostream>
#include <algorithm>

using namespace std;

#define COURSE_NUM 5
#define STUDNET_NUM 6
typedef struct student	      *PtrToS;
typedef struct course		  *PtrToC;
typedef struct RegisterNode   *PtrToR;
typedef PtrToS					SList;
typedef PtrToC					CList;
typedef PtrToR					RList;


struct RegisterNode
{
	SList Stu;
	CList Cou;
};

struct student
{
	string name;
	RList Next;
};

struct course
{
	//bool FirstRegister = true;
	string name;
	RList Next;
};


//课表
typedef struct coursetable *PtrToCT;
typedef PtrToCT				 CTList;
struct coursetable
{
	CList Cou;
	CTList Next;
};

//学生名册
typedef struct studenttable *PtrToST;
typedef PtrToST				 STList;
struct studenttable
{
	SList Stu;
	STList Next;
};

string CourseName(int tmp)
{
	switch (tmp)
	{
	case 1:  return "C1"; 
	case 2:  return "C2"; 
	case 3:  return "C3"; 
	case 4:  return "C4"; 
	case 5:  return "C5"; 
	case 6:  return "-1";//占位,最后一位while循环不会输出
	default: break;
	}
}

void InitCourseTable(CTList *CTL)
{
	CTList p,tail; CList tmpP,tmpTail;
	
	*CTL = (CTList)malloc(sizeof(coursetable));
	//为什么使用new不用malloc,参考
	//https://blog.csdn.net/fb_941219/article/details/106968262
	tmpTail = (CList)new(course);
	tmpTail->name = CourseName(1);
	tmpTail->Next = NULL;//这里是后面需要注册上去的指针
	(*CTL)->Cou = tmpTail;
	(*CTL)->Next = NULL;
	tail = *CTL;
	for (int i = 1; i <= COURSE_NUM; i++)
	{
		p = (CTList)malloc(sizeof(coursetable));
		tmpP = (CList)new(course);
		tmpP->name = CourseName(i+1);
		tmpP->Next = NULL;//这里是后面需要注册上去的指针
		p->Cou = tmpP;
		tail->Next = p;
		tail = p;
	}
	tail->Next = NULL;//记住最后一位的指针需要置为NUll
}


void DisplayCourseTable(CTList *CTL)
{
	CTList ctl;
	ctl = *CTL;
	cout << "course contents:" << endl;
	while (ctl->Next)
	{
		cout << ctl->Cou->name.c_str() << "  ";//字符串还不能直接cout,需要.c_str()
		ctl = ctl->Next;
	}
}


//void InitStudentNode(STList *STL)
//{
//	SList tmpTail;
//	*STL = (STList)malloc(sizeof(studenttable));
//	tmpTail = (SList)new(student);
//	tmpTail->name = "-1";
//	tmpTail->Next = NULL;//这里是后面需要注册上去的指针
//	(*STL)->Stu = tmpTail;
//	(*STL)->Next = NULL;
//}
//
//void InsertStudentNode(STList *STL,string StuName)
//{
//	STList stl; SList tmpStu;
//	stl = (STList)malloc(sizeof(studenttable));
//	tmpStu = (SList)new(student);
//	tmpStu->name = StuName;
//	tmpStu->Next = NULL;//这里是后面需要注册上去的指针
//	stl->Stu = tmpStu;
//	stl->Next = NULL;
//
//	(*STL)->Next = stl;
//	(*STL) = stl;
//}
//

void InitStudentTable(STList *STL, string StuName)
{
	STList stl; SList stu;
	*STL = (STList)malloc(sizeof(studenttable));
	(*STL)->Stu = (SList)new(student);
	(*STL)->Stu->name = StuName;
	(*STL)->Stu->Next = NULL;//这里是后面需要注册上去的指针
	(*STL)->Next = NULL;
}

void InsertStudentTable(STList *STL, string StuName)
{
	STList stl,tail; SList stu;

	tail = *STL;
	while (tail->Next!=NULL)
	{
		tail = tail->Next;
	}
	stl = (STList)malloc(sizeof(studenttable));
	stl->Stu = (SList)new(student);
	//stu = (SList)new(student);
	//stu->name = StuName;
	//stu->Next = NULL;//这里是后面需要注册上去的指针
	//stl->Stu = stu;
	stl->Stu->name = StuName;
	stl->Stu->Next = NULL;

	tail->Next = stl;
	tail = stl;
	tail->Next = NULL;
}



//创建一个注册节点
void CreateRegisterNode(RList *RL, string StuName, string CouName)
{
	RList rl; 
	rl = (PtrToR)malloc(sizeof(RegisterNode));
	rl->Stu = (SList)new(student);
	rl->Cou = (CList)new(course);

	rl->Stu->name = StuName;
	rl->Stu->Next = NULL;
	rl->Cou->name = CouName;
	rl->Cou->Next = NULL;
	*RL = rl;
}


//返回某一课程节点
CList FindCourseName(CTList* CTL, string CourseCname)
{
	CTList ctl;
	ctl = *CTL;
	while (ctl->Next != NULL && ctl->Cou->name != CourseCname)
		ctl = ctl->Next;
	return ctl->Cou;
}

bool FirstTimeRegister = true;
//一个学生可以选多门课程,学生注册,一个学生一个学生的注册
void RegisterStudent(CTList* CTL, STList *STL, string StuName, string CouName[],int CourseNum)
{
	
	if (FirstTimeRegister)
	{
		InitStudentTable(STL,StuName);
		//InitStudentNode(STL);
		//(*STL)->Stu->name = StuName;
		FirstTimeRegister = false;
	}else {
		//InsertStudentNode(STL, StuName);
		InsertStudentTable(STL,StuName);

	}

	CList cl;  RList rl;  STList stl;
	stl = *STL;
	while (stl->Next!=NULL) stl = stl->Next;//学生节点移动到最后一位
	for (int i=0; i<CourseNum; i++)
	{
		RList RL;//创建注册节点
		CreateRegisterNode(&RL, StuName, CouName[i]);

		if (stl->Stu->Next==NULL)//学生选的第一门课
		{
			stl->Stu->Next = RL;
		}else {
			rl = stl->Stu->Next;
			while (rl->Stu->Next != NULL) rl = rl->Stu->Next;
			rl->Stu->Next = RL;
		}
		
		cl = FindCourseName(CTL,CouName[i]);
		if (cl->Next == NULL)
		{
			cl->Next = RL;//该门课程第一次被选
		}else{
			rl = cl->Next;
			while (rl->Cou->Next != NULL) rl = rl->Cou->Next;
			rl->Cou->Next = RL;
		}
	}
}


//打印某一门课程的所有选课学生
void DisplayStudentsOfOneCourse(CList *CL)
{
	CList cl;
	cl = *CL;
	while (cl->Next != NULL)
	{
		cout << cl->Next->Stu->name.c_str() << " ";
		cl = cl->Next->Cou;
	}
}
//打印每个课程的选课学生
void DisplayCTL(CTList *CTL)
{
	CTList ctl; SList sl; CList cl;
	ctl = *CTL;
	cout <<endl<< "students of this course:" << endl;
	while (ctl->Next)
	{
		cout <<endl<< ctl->Cou->name.c_str() << "  : ";
		cl = ctl->Cou;
		DisplayStudentsOfOneCourse(&cl);
		ctl = ctl->Next;
	}
	cout<<endl;
}



//打印某一个学生选的所有课程
void DisplayCoursesOfOneStudent(SList *SL,string StuName)
{
	SList sl;
	sl = *SL;
	while (sl->Next != NULL)
	{
		if (sl->Next->Stu->name==StuName)
		{
			cout << sl->Next->Cou->name.c_str() << " ";
			sl = sl->Next->Stu;
		}else sl = sl->Next->Stu;
	}

	//输出最后一位学生
}


//打印每个学生的选课情况
void DisplaySTL(STList *STL)
{
	STList stl; CList cl; SList sl;
	stl = *STL;
	cout << endl << "courses of this student:" << endl;
	while (stl->Next)
	{
		cout << endl << stl->Stu->name.c_str() << "  : ";
		sl = stl->Stu;
		DisplayCoursesOfOneStudent(&sl, stl->Stu->name);
		stl = stl->Next;
	}
	sl = stl->Stu;
	cout << endl << stl->Stu->name.c_str() << "  : ";
	DisplayCoursesOfOneStudent(&sl, stl->Stu->name);//输出最后一位
	cout << endl << endl;
}


void StudentCourseTest()
{

	CTList CTL;
	InitCourseTable(&CTL);
	DisplayCourseTable(&CTL);

	STList STL;
	string S1 = "S1", S2 = "S2", S3 = "S3", S4 = "S4", S5 = "S5";
	string Course1[] = { "C1","C3" }, Course2[] = { "C2","C4" },
		   Course3[] = { "C1","C3" }, Course4[] = { "C1","C3" ,"C4"},
		   Course5[] = { "C2","C3" };

	int CourseNum1 = sizeof(Course1) / sizeof(string),
		CourseNum2 = sizeof(Course2) / sizeof(string),
		CourseNum3 = sizeof(Course3) / sizeof(string),
		CourseNum4 = sizeof(Course4) / sizeof(string),
		CourseNum5 = sizeof(Course5) / sizeof(string);
	RegisterStudent(&CTL, &STL, S1, Course1 ,CourseNum1);
	RegisterStudent(&CTL, &STL, S2, Course2, CourseNum2);
	RegisterStudent(&CTL, &STL, S3, Course3, CourseNum3);
	RegisterStudent(&CTL, &STL, S4, Course4, CourseNum4);
	RegisterStudent(&CTL, &STL, S5, Course5, CourseNum5);

	DisplayCTL(&CTL);//打印每门课程的选课学生
	DisplaySTL(&STL);//打印每个学生所选的课程

}


int main(int argc, char** argv)
{

	//StructPolynomialTest();
	//ListPolynomialTest();
	//RadioSortTest();
	StudentCourseTest();
	system("pause");

	return 0;
}

在这里插入图片描述

心得:基础数据结构的定义不要定义复杂了,不然代码实现过程中很绕,容易把自己给绕进去了!!!

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 、 1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READmE.文件(md如有),本项目仅用作交流学习参考,请切勿用于商业用途。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值