数据结构课程报告书

时间:2024.3.27

数 据 结 构

课程设计报告书

设计题目:        安排教学计划        

专    业:     计算机科学与技术(师范)   

班    级:        10 1          

姓    名:        关莹(李瑞男)         

指导教师:                       

                  目录

1、问题描述......................................................... 2

2、基本要求......................................................... 2

3、测试数据......................................................... 2

4、算法思想......................................................... 3

5、模块划分......................................................... 3

6、数据结构......................................................... 5

7、源程序............................................................ 5

8、界面设计....................................................... 14

9、运行与测试................................................... 14

10、总结............................................................ 19

11、思考与感悟.................................................. 19

1、问题描述

学校每个学期开设的课程是有先后顺序的,如计算机专业:开设《数据结构》课程之前,必须先开设《C语言程序设计》和《离散数学》课程,这种课程开设的先后顺序关系称为先行、后继课程关系。现在需要根据给定的课程信息及课程之间的先行、后继关系,合理安排出开设各门课程的先后顺序。

2、基本要求

1)对输入的课程先行、后继关系如果存在回路关系时应提示出现错误。

2)根据读入的课程信息及其先行、后继关系,计算出安排教学计划的序列。

3)输出教学计划的安排顺序或给出错误提示信息。

3、测试数据

正确结果:

输入:顶点数6,弧数7。

顶点为A、B、C、D、E、F。

顶点关系为 A B、A C、B C、C D、C E、D E、E F。

             输出:A->B->C->D->E->F

错误结果

1)输入:顶点数1,弧数5。

   输出:顶点数或弧数不正确,有向图建立失败!

2)输入:顶点数6,弧数8。

         顶点为A、B、C、D、E、F。

         顶点关系为A B、AG。

   输出:顶点G不存在,有向图建立失败!

3)输入:顶点数6,弧数8。

         顶点为A、B、C、D、E、F。

          顶点关系为A B、A C、B C、C D、C E、D E、E F、F D。

    输出:该有向图有回路,无法完成拓扑排序。

4、算法思想

1、采用邻接表存储结构实现有向图;有向图需通过顶点数、弧数、顶点以及弧等信息建立。

2、拓扑排序算法void TopologicalSort(ALGraph G) 中,先输出入度为零的顶点,然后输出新的入度为零的顶点,此操作利用栈实现。

3、拓扑排序算法void TopologicalSort(ALGraph G),大体思想为:

    1)遍历有向图各顶点的入度,将所有入度为零的顶点入栈;

    2)栈非空时,输出一个顶点,并对输出的顶点数计数;

    3)该顶点的所有邻接点入度减一,若减一后入度为零则入栈;

    4)重复2)、3),直到栈空,若输出的顶点数与图的顶点数相等则该图可拓扑排序,否则图中有环;

5、模块划分

1、顺序栈操作

1) void Initstack(ssqstack *S)

功能:初始化顺序栈

2) int emptystack(sqstack S)

功能:判断栈空。栈空返回 1;栈非空返回 0

3) int push(sqstack *S,ElemType e)

功能:元素入栈

4) int pop(sqstack *S,ElemType *e)

功能:元素出栈

2、有向图(DAG)邻接表存储结构(ALG)的操作

1) int LocateVex(ALGraph G,VertexType v)

功能:顶点在头结点数组中的定位

2) int CreateGraph(ALGraph *G)

功能:建立图。函数内包含了由用户输入顶点数、弧数、顶点以及弧的操作

错误判断:包含顶点数、弧数是否正确的判断;包含用户输入的弧的顶点是否存在的判断

3) void PrintGraph(ALGraph G)

功能:输出有向图

4) int CreateGraph2(ALGraph *G)

功能:建立预置课程图(输出函数内预置课程信息,并自动建立有向图)图建立成功返回1;图建立失败返回0

错误判断:包含顶点数、弧数是否正确的判断。包含弧的顶点是否存在的判断

3、拓扑排序

1) void TopologicalSort(ALGraph G)

功能:实现拓扑排序

错误判断:包含有向图是否有回路的判断

4、主函数

void main()

功能:主函数。利用while语句和switch语句实现菜单化调用函数

各模块之间的调用关系图:

6、数据结构

1、顺序栈的存储类型为:

typedef int ElemType;

typedef struct QNode

{   int top;

ElemType *base;

Int stacksize;

}   QNode,sqstack;

理由:用栈来存储入度为0的顶点,符合栈先进后出的特点。

    2、图的类型(邻接表存储结构)为:

typedef char VertexType[20];//顶点信息(名称)

typedef struct ArcNode//链表结点

{   int vexpos;//该弧所指向的顶点在数组中的位置

   struct ArcNode *next;//指向当前起点的下一条弧的指针

}   ArcNode;

typedef struct VNode//头结点

{   VertexType name;//顶点信息(名称)

   int indegree;//顶点入度

   ArcNode *firstarc;//指向当前顶点的第一条弧的指针

}   VNode,AdjList[MAXVEX];

typedef struct

{   AdjList vexhead;//邻接表头结点数组

   int vexnum,arcnum;//图的顶点数和弧数

}   ALGraph;

理由:此程序的有向图为稀疏图,符合邻接表的特点。

7、源程序

(1)程序中包括的文件清单:1.c

(2)文件中包括的函数清单:

1)顺序栈:void Initstack(ssqstack *S)

2)有向图邻接表:void PrintGraph(ALGraph G)

                 int CreateGraph2(ALGraph *G)

3)拓扑排序:void TopologicalSort(ALGraph G)

(3)源程序

#include "stdlib.h"

#include "stdio.h"

#include "string.h"//字符数组

/*******************************************/

/*           以下为顺序栈操作              */

/*******************************************/

/* 定义顺序栈类型 */

#define MAXNUM 30

#define INITSIZE 100

typedef int ElemType;

typedef struct QNode

{    int top;

      ElemType *base;

      int stacksize;

}    QNode,sqstack;

/* 1.初始化 */

void Initstack(sqstack *S)

{    S->base=(ElemType *)malloc(INITSIZE*sizeof(ElemType));

      S->top=0;

      S->stacksize=INITSIZE;

}

/* 2.判断栈空 */

int emptystack(sqstack S)

{    if(S.top==0)

             return 1;

      else

             return 0; }

/* 3.入栈 */

int push(sqstack *S, ElemType e)

{   

      if(S->top>=S->stacksize);

      {S->base=(ElemType *)realloc(S->base,(S->stacksize+1) *sizeof(ElemType));

      if(!S->base) return 0;

      S->stacksize++;

      }

      S->base[S->top++]=e;

      return 1;

}

/* 4.出栈 */

int pop(sqstack *S,ElemType *e)//*e记录出栈元素的变量

{    //int i;

    if(S->top==0) return 0;

      *e=S->base[--S->top];

      return 1;

}

/****************************************************/

/*    以下为有向图(DAG)邻接表存储结构(ALG)的操作    */

/****************************************************/

#define MAXVEX 30 //最大顶点个数

#define MAXNAME 20

typedef char VertexType[20]; //顶点信息(名称)

/* 图的类型定义(邻接表存储结构) */

typedef struct ArcNode //链表结点

{    int vexpos; //该弧所指向的顶点在数组中的位置

      struct ArcNode *next; //指向当前起点的下一条弧的指针

}    ArcNode;

typedef struct VNode //头结点

{    VertexType name; //顶点信息(名称)

      int indegree; //顶点入度

      ArcNode *firstarc; //指向当前顶点的第一条弧的指针

}    VNode,AdjList[MAXVEX];

typedef struct

{    AdjList vexhead; //邻接表头结点数组

      int vexnum,arcnum; //图的顶点数和弧数

}    ALGraph;

/* 5.顶点在头结点数组中的定位 */

int LocateVex(ALGraph G,VertexType v)//G带操作的图;v要在图中定位的顶点

{    int i;

      for(i=0;i<G.vexnum;i++)

             if(strcmp(v,G.vexhead[i].name)==0) break;

      return i; }//顶点存在则返回在头结点数组中的下标;否则返回图的定点数

/* 6.建立图(邻接表) */

int CreateGraph(ALGraph *G) //成功建立返回1,不成功则返回0

{    int i,j,k; VertexType v1,v2;ArcNode *newarc;

      printf("\n输入有向图顶点数和弧数vexnum,arcnum:"); //输入顶点数和弧数

      scanf("%d,%d",&(*G).vexnum,&(*G).arcnum); //输入并判断顶点数和弧数是否正确

      if((*G).vexnum<0||(*G).arcnum<0||(*G).arcnum>(*G).vexnum*((*G).vexnum-1))

             {     printf("\n顶点数或弧数不正确,有向图建立失败!\n");return 0; }

      printf("\n输入 %d 个顶点:",(*G).vexnum); //输入顶点名称

      for(i=0;i<(*G).vexnum;i++)

             {     scanf("%s",(*G).vexhead[i].name); }

      printf("\n顶点列表:\n共有%d个顶点:   ",(*G).vexnum);//输出顶点名称

      for(i=0;i<(*G).vexnum;i++)

             printf("%s   ",(*G).vexhead[i].name);

      for(i=0;i<(*G).vexnum;i++) //邻接表初始化

             {     (*G).vexhead[i].firstarc=NULL;

                    (*G).vexhead[i].indegree=0;}

      printf("\n\n输入 %d 条边:vi vj\n",(*G).arcnum); //输入有向图的边

      for(k=0;k<(*G).arcnum;k++)

             {     scanf("%s%s",v1,v2); //v1是弧的起点(先决条件),v2是弧的终点

                    i=LocateVex(*G,v1);j=LocateVex(*G,v2); //定位顶点并判断顶点是否存在

                    if(i>=(*G).vexnum)

                           {     printf("顶点%s不存在,有向图建立失败!\n",v1);return 0; }                        if(j>=(*G).vexnum)

                           {     printf("顶点%s不存在,有向图建立失败!\n",v2);return 0; }

                    newarc=(ArcNode*)malloc(sizeof(ArcNode)); //前插法建顶点链表

                    newarc->vexpos=j;

                    if((*G).vexhead[i].firstarc==NULL)

                           {     newarc->next=NULL;

                                  (*G).vexhead[i].firstarc=newarc; }

                    else

                           {     newarc->next=(*G).vexhead[i].firstarc->next;

                                  (*G).vexhead[i].firstarc->next=newarc; }

                    (*G).vexhead[j].indegree++; //对应顶点入度计数加1

             }

      printf("\n有向图建立成功!\n");

      return 1;

}

/* 7.按邻接表方式输出有向图 */

void PrintGraph(ALGraph G)

{    int i;ArcNode *p;

      printf("\n输出有向图:\n");

      for(i=0; i<G.vexnum; i++)

             {     printf("\n顶点:%s   ",G.vexhead[i].name);

                    printf("入度:%3d\n",G.vexhead[i].indegree);

                    p=G.vexhead[i].firstarc;

                    printf("邻接点:");

                    while(p!=NULL)

                           {     printf("%s   ",G.vexhead[p->vexpos].name);

                                  p=p->next; }

                    printf("\n");

             }

}

//为避免演示时要输入过多数据,以下函数将课程编号、课程间的先后关系通过数组预置

/* 8.建立预置课程图(邻接表) */

int CreateGraph2(ALGraph *G) //成功建立返回1,不成功则返回0

{    int i,j,k;  VertexType v1,v2;      ArcNode *newarc;

      VertexType   SubjectName[12]={   "C1","C2","C3","C4", //课程名称

      "C5","C6","C7","C8",

      "C9","C10","C11","C12" },    

             RelationV1[16]={      "C1","C1","C2","C1", //基础课

      "C3","C4","C11","C5",

      "C3","C3","C6","C9",

      "C9","C9","C10","C11"},

             RelationV2[16]={      "C2","C3","C3","C4", //以上面课程为基础的课

      "C5","C5","C6","C7",

      "C7","C8","C8","C10",

      "C11","C12","C12","C12",};

//********************************************************************

      //system("PAUSE");

      (*G).vexnum=12;       (*G).arcnum=16;

      if((*G).vexnum<0||(*G).arcnum<0||(*G).arcnum>(*G).vexnum*((*G).vexnum-1))

             {     printf("\n课程数或先后关系不正确,有向图建立失败!\n");

                    return 0;} //判断课程数和弧数是否正确

      for(i=0;i<(*G).vexnum;i++)

             {     strcpy((*G).vexhead[i].name,SubjectName[i]); }

      for(i=0;i<(*G).vexnum;i++) //邻接表初始化

             {     (*G).vexhead[i].firstarc=NULL;

                    (*G).vexhead[i].indegree=0; }

      for(k=0;k<(*G).arcnum;k++)

             {     strcpy(v1,RelationV1[k]); strcpy(v2,RelationV2[k]);

                    i=LocateVex(*G,v1);j=LocateVex(*G,v2); //定位课程并判断课程是否存在

                    if(i>=(*G).vexnum)

                           {     printf("课程%s不存在,有向图建立失败!\n",v1);return 0; }

                    if(j>=(*G).vexnum)

                           {     printf("课程%s不存在,有向图建立失败!\n",v2);return 0; }

                    newarc=(ArcNode*)malloc(sizeof(ArcNode)); //前插法建课程链表

                    newarc->vexpos=j;

                    if((*G).vexhead[i].firstarc==NULL)

                           {     newarc->next=NULL;

                                  (*G).vexhead[i].firstarc=newarc; }

                    else

                           {     newarc->next=(*G).vexhead[i].firstarc->next;

                                  (*G).vexhead[i].firstarc->next=newarc; }

                    (*G).vexhead[j].indegree++; //对应课程入度计数加1

             }

      printf("\n有向图建立成功!\n");

      return 1;

}

/**********************************/

/*       以下为拓扑排序算法       */

/**********************************/

/* 9.拓扑排序 */

void TopologicalSort(ALGraph G)

{    int i,k,count;ElemType e;ArcNode *p;//弧结点,指向边表结点的指针

      sqstack S; /*定义栈*/

      Initstack(&S);

      for(i=0; i<G.vexnum; i++) //零入度课程入栈

             if(!G.vexhead[i].indegree) push(&S,i);

      count=0; //对输出课程计数变量初始化

      printf("\n\n\n以上课程的一个拓扑排序序列为:\n");

      while(!emptystack(S))

      {     pop(&S,&e);  //先将入度为零的课程输出

             printf("%s->",G.vexhead[e].name);

             count++; //对输出的顶点计数

             for(p=G.vexhead[e].firstarc;p;p=p->next) //遍历当前课程的邻接点

             {     k=p->vexpos; //邻接点位置

                    if(!(--G.vexhead[k].indegree)) //每个邻接点入度减1后若为零则入栈

                           push(&S,k);

             }

      }

      printf("\n");

      if(count<G.vexnum)

             {     printf("\n该有向图有回路,无法完成拓扑排序!\n"); }

}

void main()

{    ALGraph G; int menu;

      while(1){

      printf("\n             **********************************************\n");

      printf("         *     1.建立有向图并求一个拓扑排序序列     *\n");

      printf("         *     2.清屏                               *\n");

      printf("         *     3.退出                               *\n");

      printf("         **********************************************\n");

      printf("                请输入你的选择:");

      scanf("%d",&menu);

      switch(menu){

      case 1:

             if(CreateGraph(&G)) //有向图建成则执操作

                    {     system("PAUSE");//暂停,等待用户按键

                           PrintGraph(G);system("PAUSE");//按邻接表方式输出有向图

                           TopologicalSort(G); }//拓扑排序

             break;

      case 2:

             system("CLS");//清屏

             break;

      case 3:

             return;//退出当前函数,返回调用点

                    }

      }

}

8、界面设计

运行程序后显示菜单,选择1建立有向图并求出一个拓扑排序序列。根据提示输入有向图定点数和弧数vexnum,arcnum。输入顶点,然后再输入边。程序会根据用户所输入的数据输出每个定点的入度、邻接点及拓扑排序结果。选择2为清屏,选择3为退出程序。

9、运行与测试

1.      主界面

2.选择1建立有向图并求一个拓扑排序序列,输入顶点并输出。

3.输入有向图的弧,有向图建立成功。

   

   

4.输出各顶点的入度及邻接点

   

   

5.根据用户的输入信息输出一个拓扑排序序列

6.若输入错误的顶点和弧数信息

7.若输入弧的顶点不存在

8.若存在回路

10、总结

(1) 邻接表:占用空间少,节省空间。有向图容易求顶点出度。求入度不容易,要遍历整个表。

 拓扑排序:可以让许多混乱无序的点变得容易扩展。

(2)邻接表:T(n)=O(e)   S(n)=O(n+e)

(3)还可以用队列来存储入度为0的点,利用邻接矩阵存储邻接点;

(4)功能拓展:可以输出有向图各个顶点及其入度数与邻接点,让用户一目了然。

(5)帮助:让用户自己输入一个拓扑序列,程序对其正确与否进行检测。

11、思考与感悟

      刚开始不知道从哪里入手,后来根据老师给的提示,自己也查阅了一些有关拓扑排序的资料,渐渐地理出了头绪。有时候错误很多,但只要改对一个地方就没有错误了。

通过课程设计,我们对图的概念、拓扑排序有了新的认识。无论是从学习上还是从自身角度,都得到了很大的提高。发现了许多在理论学习中无法发现的问题。同时,通过自己的努力,顺利的解决了这些问题,这也是一种磨砺。

这次课程设计,为我们提供了与众不同的学习方法和学习机会。通过c语言完成课程设计,让我们从传统上的被动授学,转变为主动求学。形成了在实践中学习的能力,增强了领悟能力和解决问题能力。

更多相关推荐:
数据结构课程设计报告

数据结构课程设计报告题目5班级计算机1102学号4111110030姓名陈越指导老师王新胜1一需求分析1运行环境TC2程序所需实现的功能几种排序算法的演示要求给出从初始开始时的每一趟的变化情况并对各种排序算法性...

数据结构课程设计报告模板

课程设计说明书课程名称:数据结构与算法专业:计算机科学与技术班级:103013姓名:XXX学号:03指导教师:XXX完成日期:20XX年1月12日任务书题目:黑白棋系统设计内容及要求:1.课程设计任务内容通过玩…

数据结构课程设计报告(含代码)

西安郵電學院数据结构课程设计报告题目校园导航系统院系名称计算机学院专业名称计算机科学与技术班级学生姓名学号8位指导教师设计起止时间20xx年12月11日20xx年12月15日一设计目的1通过本次课程设计巩固数据...

数据结构课程设计报告书

南通大学计算机学院数据结构课程设计报告书题目校园十大优秀青年评比专业计算机科学与技术班级姓名学号指导教师开始日期20xx114完成日期20xx1161数据结构课程设计1问题的描述和分析11问题描述新一届校园十大...

数据结构课程报告

数据结构课程报告姓名周涛学号20xx130403221问题描述与功能设计本程序要求能够实现从键盘键入两个多项式的系数指数相关数据后能够进行多项式输出多项式相加多项式相减的运算数据结构与算法多项式的逻辑结构视为线...

数据结构课程设计报告模板

青岛理工大学数据结构课程设计报告题目宿舍管理查询软件院系计算机工程学院学生姓名谢茂盛班级网络121学号20xx07131起迄日期20xx070720xx0720指导教师张艳一需求分析所有大标题宋体加粗四号下同小...

《数据结构课程设计报告》

安徽省巢湖学院计算机与信息工程学院课程设计报告课程名称课题名称用三元组实现稀疏矩阵的转置相加相乘专业计算机科学与技术班级学号AA姓名AAA联系方式136XXXXXXXX指导教师武彬20年月日目录1数据结构课程设...

数据结构课程设计报告

数据结构课程设计报告身份证信息管理系统学院:理学院专业:信息与计算科学班级:学号:姓名:需求分析通过学习数据结构这门课程,我们学习了很多存储数据的方法,当然不同的方法对于对数据的查找有不同的效率。本课题要求建立…

20xx数据结构课程设计报告

沈阳航空航天大学课程设计报告课程设计名称:数据结构课程设计课程设计题目:树与二叉树转换院(系):专业:班级:学号:姓名:指导教师:完成日期:目录第1章题目内容与要求...11基本功能...12功能分解...1第…

数据结构课程设计报告

一题目奇数阶幻方求解问题描述幻方是一种很有意思的数字矩阵在很早著名的九宫八卦阵就与幻方有关幻方的定义为1到NN的整数填入NN的方格中每行和每列以及对角线的数字之和必须是相等的你作为八卦公司的顶级程序员现在需要你...

数据结构课程设计报告(c++)

数据结构课程设计报告题目2用无序的顺序表实现一个城市数据库专业班级112学号20xx41404207姓名符日富同组人员吴为密周金驰邱李棚一课程设计的内容要求2用无序的顺序表实现一个城市数据库每条数据库记录包括城...

数据结构课程设计报告(含源码)

重庆科技学院课程设计报告院系电气与信息工程学院专业班级计科普0902学生姓名邓小祥学号20xx441656设计地点单位计算机基础自主学习中心I306设计题目停车场管理系统设计完成日期20xx年1月14日指导教师...

数据结构课程报告(45篇)