链表的应用---学生注册课程(多重表)

多重表,是在《数据结构与算法分析—C语言描述》书上介绍的一种方法,用于解决学生注册问题的。

原题目是,一所有40000名学生和2500门课程的大学需要生成两种类型的报告。第一个报告列出每个班的注册者,第二个报告列出每个学生注册的班级。

常用的实现方法是使用二维数组,这样一个数组将有1亿项。平均一个学生注册三门课程,因此实际上有意义的数据只有120000项,大约占0.1%。

按照书中介绍,利用多重表的方法来替代二维数组的实现,可以节省很多空间,详见下图

这里写图片描述

通过将班级表和学生表串起来,所有的表都各有一个表头并且都是循环的。由上图可以看出,中间的节点有两个指针域,一个指向学生,一个指向班级。

我的实现,并没有用循环链表,每当一个学生注册一门课程的时候,就在该学生的表头插入该课程的信息,在该课程的表头插入该学生的信息。如果需要打印某个学生选了哪些课程,就直接找到这个学生的表头开始遍历,课程也是一样。下面看具体代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define NAME_LEN 10


/* Assume there have three Courses and four Students */
typedef enum
{
    CHINESE = 1,              
    ENGLISH,
    MATH,                   
}e_COURSE_TYPE;

#define STUA    "Tom"
#define STUB    "Mary"
#define STUC    "Jake"
#define STUD    "Ray"


typedef struct _Node_T
{
    char name[NAME_LEN];
    e_COURSE_TYPE course;       
    struct _Node_T *next;   
}Node;

typedef struct _Node_T * Head;

struct _Node_T * StuA;
struct _Node_T * StuB;
struct _Node_T * StuC;
struct _Node_T * StuD;
struct _Node_T * CourseCH;
struct _Node_T * CourseEN;
struct _Node_T * CourseMA;


Node * multi_lists_make_node(void)
{
    Node  * node = (Node *)malloc(sizeof(Node));
    if(NULL == node)
    {
        printf("node malloc fail!\n");
        return NULL;
    }
    memset(node, 0, sizeof(Node));

    memset(node->name, 0, sizeof(char)*NAME_LEN);
    node->course = 0;
    node->next = NULL;

    return node;
}

void multi_lists_init(void)
{
    StuA = multi_lists_make_node();
    strcpy(StuA->name, STUA);
    StuB = multi_lists_make_node();
    strcpy(StuB->name, STUB);
    StuC = multi_lists_make_node();
    strcpy(StuC->name, STUC);
    StuD = multi_lists_make_node();
    strcpy(StuD->name, STUD);

    CourseCH = multi_lists_make_node();
    CourseCH->course = CHINESE;
    CourseEN = multi_lists_make_node();
    CourseEN->course = ENGLISH;
    CourseMA = multi_lists_make_node();
    CourseMA->course = MATH;
}

/* Get the head pointer of the Student */
Head multi_lists_get_head_by_name(char * student)
{
    if( (NULL != StuA) && (0 == strcmp(StuA->name, student)) )
    {
        return StuA;
    }

    if( (NULL != StuB) && (0 == strcmp(StuB->name, student)) )
    {
        return StuB;
    }

    if( (NULL != StuC) && (0 == strcmp(StuC->name, student)) )
    {
        return StuC;
    }

    if( (NULL != StuD) && (0 == strcmp(StuD->name, student)) )
    {
        return StuD;
    }

    return NULL;
}

/* Get the head pointer of the Course */
Head multi_lists_get_head_by_course(e_COURSE_TYPE course)
{
    if( (NULL != CourseCH) && (CourseCH->course == course) )
    {
        return CourseCH;
    }

    if( (NULL != CourseEN) && (CourseEN->course == course) )
    {
        return CourseEN;
    }

    if( (NULL != CourseMA) && (CourseMA->course == course) )
    {
        return CourseMA;
    }

    return NULL;
}

/* Judge Function : If Student choose the same Course, it will return true */
bool multi_lists_same_course(Node * pStu, e_COURSE_TYPE course)
{
    Node * pTemp = pStu;

    while(pTemp->next)
    {
        if(pTemp->next->course == course)
            return true;

        pTemp = pTemp->next;
    }

    return false;
}

/* Judge Function : If the Course have the same Student, it will return true */
bool multi_lists_same_student(Node * pCour, char * student)
{
    Node * pTemp = pCour;

    while(pTemp->next)
    {
        if(0 == strcmp(pCour->next->name, student))
            return true;

        pTemp = pTemp->next;
    }

    return false;
}

/* Register the Course and the Student */
void multi_lists_course_register(char *student, e_COURSE_TYPE course)
{
    Node * pStu = multi_lists_get_head_by_name(student);
    if(NULL == pStu)
    {
        printf("No this student, ignore it\n");
        return;
    }

    /* Ignoe the student register the same course */
    if(false == multi_lists_same_course(pStu, course))
    {
        // insert node of the front the list
        Node * newCourse = multi_lists_make_node();
        newCourse->course = course;
        newCourse->next = pStu->next;

        pStu->next = newCourse;
    }

    Node * pCour = multi_lists_get_head_by_course(course);
    if(NULL == pCour)
    {
        printf("No this Course, ignore it\n");
        return;
    }

    /* Ignore the Course register the same student */
    if(false == multi_lists_same_student(pCour, student))
    {        
        // insert node of the front the list
        Node * newStu = multi_lists_make_node();
        strcpy(newStu->name, student);
        newStu->next = pCour->next;

        pCour->next = newStu;  
    }
}

/* Unregister the Course and the Student */
void multi_lists_course_unregister(char *student, e_COURSE_TYPE course)
{
    Node * pStu = multi_lists_get_head_by_name(student);
    if(NULL == pStu)
    {
        printf("No this student, ignore it\n");
        return;
    }

    Node * pCour = multi_lists_get_head_by_course(course);
    if(NULL == pCour)
    {
        printf("No this Course, ignore it\n");
        return;
    }

    Node * pTemp = NULL;

    /* free the Course Node from the Student List */
    while(pStu->next)
    {
        if(pStu->next->course == course)
        {
            pTemp = pStu->next;
            pStu->next = pTemp->next;
            free(pTemp);
            break;
        }
        pStu = pStu->next;
    }

    /* free the Student Node from the Course List */
    while(pCour->next)
    {
        if(0 == strcmp(pCour->next->name, student) )
        {
            pTemp = pCour->next;
            pCour->next = pTemp->next;
            free(pTemp);
            break;
        }
        pCour = pCour->next;
    }
}

void multi_lists_print_format(e_COURSE_TYPE course)
{
    if(CHINESE == course)
        printf("%-7s ", "Chinese");
    else if(ENGLISH == course)
        printf("%-7s ", "English");
    else if(MATH == course)
        printf("%-7s ", "Math");
}

/* print the student choose which course */
void multi_lists_traverse_stu(char *student)
{
    Node * pStu = multi_lists_get_head_by_name(student);
    if(NULL == pStu)
    {
        printf("No this student, ignore it\n");
        return;
    }

    printf("%5s choose Course : ", student);

    while(pStu->next)
    {
        multi_lists_print_format(pStu->next->course);
        pStu = pStu->next;
    }

    printf("\n");
}

/* print who is in the course */
void multi_lists_traverse_course(e_COURSE_TYPE course)
{
    Node * pCour = multi_lists_get_head_by_course(course);
    if(NULL == pCour)
    {
        printf("No this Course, ignore it\n");
        return;
    }

    printf("Course( ");
    multi_lists_print_format(course);
    printf(")have students : ");

    while(pCour->next)
    {
        printf("%s  ", pCour->next->name);
        pCour = pCour->next;
    }

    printf("\n");
}

/* Test Function */
void multi_lists_main_test(void)
{
    multi_lists_init();

    multi_lists_course_register(STUA, CHINESE);
    multi_lists_course_register(STUA, ENGLISH);
    multi_lists_course_register(STUA, MATH);
    multi_lists_course_register(STUB, CHINESE);
    multi_lists_course_register(STUB, MATH);
    multi_lists_course_register(STUC, CHINESE);

    multi_lists_course_unregister(STUA, ENGLISH);
    multi_lists_course_unregister(STUB, MATH);

    multi_lists_traverse_stu(STUA);
    multi_lists_traverse_stu(STUB);

    multi_lists_traverse_course(CHINESE);
    multi_lists_traverse_course(MATH);
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值