提交 b6fc32ab 创建 作者: 宋海霞's avatar 宋海霞

template

上级
流水线 #481 已失败 于阶段
/Debug
/Release
*.bak
image: "registry.cn-hangzhou.aliyuncs.com/engintime/ubuntu_16.04_cpp:latest"
stages:
- make
- case1
- teacher-check
variables:
TEMPLATE_REPO: "engintime/ds-lab/Project-Template/Lab016.git"
.codecode-runner: &codecode-runner
tags:
- ubuntu-16.04
- short-job
make:
stage: make
<<: *codecode-runner
script:
- make
- execscore.sh 40
only:
- master
case1:
stage: case1
<<: *codecode-runner
script:
- make
- ./app > user_output.txt
- diff output.txt user_output.txt -b -B -y -i --suppress-common-lines
- execscore.sh 100
only:
- master
teacher-check:
stage: teacher-check
<<: *codecode-runner
script:
- make
- ./app
- git clone ${CODECODE_PROTOCOL}gitlab-ci-token:${CI_JOB_TOKEN}@${CODECODE_DOMAIN}/${TEMPLATE_REPO} template
- diff template/.gitlab-ci.yml .gitlab-ci.yml -b -B -y -i --suppress-common-lines
- diff template/output.txt output.txt -b -B -y -i --suppress-common-lines
- fileidentity.sh
only:
- master
when: manual
allow_failure: false
#ifndef _GRAPH_H_
#define _GRAPH_H_
//
// 在此处包含 C 标准库头文件
//
#include <stdio.h>
//
// 在此处包含其他头文件
//
#include "Queue.h"
//
// 在此处定义数据结构
//
#define MAX_VERTEX_NUM 50 // 顶点最大数量
// 边(弧)
typedef struct ArcNode {
int vertex; // 顶点域。即顶点在顶点数组中的下标。
struct ArcNode* next; // 链域。指向下一条边(弧)。
}ArcNode;
// 顶点
typedef struct VexNode {
const char* name; // 使用一个字符串作为顶点保存的值。也可以认为是顶点的名字。
struct ArcNode* firstarc; // 指向第一条边(弧)。
}VexNode;
// 图。使用邻接表存储
typedef struct Graph {
VexNode vexlist[MAX_VERTEX_NUM]; // 顶点表
int length; // 顶点数量
}Graph;
//
// 在此处声明函数
//
void BreadthFirstSearch(Graph* pGraph);
void InitGraph(Graph* pGraph);
void DeleteGraph(Graph* pGraph);
//
// 在此处声明全局变量
//
extern int visited[MAX_VERTEX_NUM];
extern Queue queue;
#endif /* _GRAPH_H_ */
<?xml version="1.0" encoding="gb2312"?>
<OSLProject Version="1.00" Name="Graph_BreadthFirstSearch" SubjectID="cf4dda31-1275-49ef-9b0f-36a6eff372e4" ProjectTemplateID="07c2e815-4160-4535-989e-51272cce1b51">
<Configurations>
<Configuration Name="Debug">
<Tool Name="PreBuildEventTool"/>
<Tool Name="CustomBuildTool"/>
<Tool Name="GCCCompilerTool" PreprocessorDefinitions="_DEBUG" GenerateDebugInformation="-1"/>
<Tool Name="PreLinkEventTool"/>
<Tool Name="GCCLinkerTool" AdditionalDependencies="&quot;$(DSLInstallDir)Dump\lib\Graph_BreadthFirstSearch_Demo.o&quot;"/>
<Tool Name="PostBuildEventTool"/>
<VisualContext>
<WatchPoints>
<WatchPoint FunctionName="BreadthFirstSearch" ObserverID="1F67AC89-DAB4-454a-B7DD-8FC4406AD6EE">
</WatchPoint>
</WatchPoints>
</VisualContext>
</Configuration>
<Configuration Name="Release">
<Tool Name="PreBuildEventTool"/>
<Tool Name="CustomBuildTool"/>
<Tool Name="GCCCompilerTool" PreprocessorDefinitions="NDEBUG"/>
<Tool Name="PreLinkEventTool"/>
<Tool Name="GCCLinkerTool"/>
<Tool Name="PostBuildEventTool"/>
</Configuration>
</Configurations>
<Files>
<Filter Name="ͷļ" Filter="h;hpp;hxx">
<File RelativePath=".\Graph.h">
</File>
<File RelativePath=".\Queue.h">
</File>
</Filter>
<Filter Name="Դļ" Filter="cpp;c;cc;cxx">
<File RelativePath=".\main.c">
</File>
<File RelativePath=".\Queue.c">
</File>
</Filter>
<File RelativePath=".\makefile">
</File>
<File RelativePath=".\output.txt">
</File>
<File RelativePath=".\readme.md">
</File>
</Files>
</OSLProject>
#include "Queue.h"
/*
功能:
初始化队列。
参数:
pQ -- 队列指针
*/
void InitQueue(Queue* pQ)
{
pQ->begin = pQ->end = 0;
pQ->length = 0;
}
/*
功能:
将元素插入队尾。
参数:
pQ -- 队列指针
Elem -- 入队的元素
返回值:
如果插入成功返回入队元素的值。
如果插入失败返回 -1。
*/
int EnQueue(Queue* pQ, int Elem)
{
//
// 队列满,入队失败。
//
if(MAX_QUEUE_LENGTH == pQ->length)
return -1;
pQ->buffer[pQ->end] = Elem;
pQ->end = (pQ->end + 1) % MAX_QUEUE_LENGTH;
pQ->length++;
return Elem;
}
/*
功能:
将队首元素出队
参数:
pQ -- 队列指针
返回值:
如果出队成功返回出队元素的值。
如果出队失败返回 -1。
*/
int DeQueue(Queue* pQ)
{
int Elem;
//
// 队列空,出队失败
//
if(QueueEmpty(pQ))
return -1;
Elem = pQ->buffer[pQ->begin];
pQ->begin = (pQ->begin + 1) % MAX_QUEUE_LENGTH;
pQ->length--;
return Elem;
}
/*
功能:
判断队列是否为空。
参数:
pQ -- 队列指针
返回值:
如果队列空返回 1(真)
如果队列非空返回 0(假)
*/
int QueueEmpty(Queue* pQ)
{
return 0 == pQ->length ? 1 : 0;
}
#ifndef _QUEUE_H_
#define _QUEUE_H_
//
// 在此处包含 C 标准库头文件
//
//
// 在此处包含其他头文件
//
//
// 在此处定义数据结构
//
#define MAX_QUEUE_LENGTH 64 // 队列最大长度
// 环形队列
typedef struct Queue{
int buffer[MAX_QUEUE_LENGTH]; // 队列缓冲区
int begin; // 开始位置
int end; // 结束位置
int length; // 队列长度
}Queue;
//
// 在此处声明函数
//
void InitQueue(Queue* pQ);
int EnQueue(Queue* pQ, int Elem);
int DeQueue(Queue* pQ);
int QueueEmpty(Queue* pQ);
//
// 在此处声明全局变量
//
#endif /* _QUEUE_H_ */
#include "Graph.h"
int visited[MAX_VERTEX_NUM]; // 顶点访问标志数组。0 表示未访问;大于 0 表示访问的先后次序。
Queue queue; // 队列
int main(int argc, char* argv[])
{
Graph graph;
int i, j;
//
// 初始化图
//
InitGraph(&graph);
//
// 初始化队列
//
InitQueue(&queue);
//
// 初始化访问标志数组
//
for(i=0; i<graph.length; i++)
visited[i] = 0;
//
// 广度优先搜索
//
BreadthFirstSearch(&graph);
for(i=0; i<graph.length; i++)
{
for(j=0; j<graph.length; j++)
{
if(visited[j] == i+1)
{
printf("%s ", graph.vexlist[j].name);
}
}
}
printf("\n");
//
// 销毁图
//
DeleteGraph(&graph);
return 0;
}
/*
功能:
广度优先搜索。
参数:
pGraph -- 图指针
*/
void BreadthFirstSearch(Graph* pGraph)
{
ArcNode* pArcNode; // 边(弧)节点指针
int i, v; // 顶点序号。从 0 开始计数。
int nVisitCount = 0; // 访问计数器。
//
// TODO: 在此添加代码
//
return;
}
/*
功能:
使用给定的数据初始化图的邻接表
参数:
pGraph -- 图指针
*/
typedef struct VertexArrayEntry {
const char* name; // 顶点名称。NULL 表示顶点序列结束。
int VexIndex[MAX_VERTEX_NUM]; // 与该顶点邻接的顶点序列。-1 表示序列结束。
}VertexArrayEntry;
const VertexArrayEntry VertexArray[] = {
{ "V0", {2, 5, 1, -1} },
{ "V1", {3, 6, 2, -1} },
{ "V2", {0, 3, 6, 1, -1} },
{ "V3", {1, 2, 4, -1} },
{ "V4", {1, 3, -1} },
{ "V5", {0, 6, -1} },
{ "V6", {2, 5, 0, -1} },
{ NULL } // 结束标志
};
void InitGraph(Graph* pGraph)
{
int i, j;
ArcNode** pArcNodePtr; // 指向指针的指针
//
// 重置图中的数据
//
pGraph->length = 0;
//
// 使用给定的数据初始化图的邻接表
//
for(i=0; i<MAX_VERTEX_NUM ;i++)
{
if(NULL == VertexArray[i].name)
break;
pGraph->vexlist[i].name = VertexArray[i].name;
pArcNodePtr = &pGraph->vexlist[i].firstarc;
for(j=0; j<MAX_VERTEX_NUM; j++)
{
if(-1 == VertexArray[i].VexIndex[j])
{
*pArcNodePtr = NULL;
break;
}
*pArcNodePtr = (ArcNode*)malloc(sizeof(ArcNode));
(*pArcNodePtr)->vertex = VertexArray[i].VexIndex[j];
pArcNodePtr = &(*pArcNodePtr)->next;
}
pGraph->length++;
}
}
/*
功能:
销毁图
参数:
pGraph -- 图指针
*/
void DeleteGraph(Graph* pGraph)
{
int i;
ArcNode* pArcNode;
for(i=0; i<pGraph->length; i++)
{
while(pGraph->vexlist[i].firstarc != NULL)
{
pArcNode = pGraph->vexlist[i].firstarc;
pGraph->vexlist[i].firstarc = pArcNode->next;
free(pArcNode);
}
}
pGraph->length = 0;
}
app:main.o Queue.o
gcc main.o Queue.o -o app
main.o:main.c Graph.h
gcc -c -w -O3 -std=c99 -fsigned-char main.c -o main.o
Queue.o:Queue.c Queue.h
gcc -c -w -O3 -std=c99 -fsigned-char Queue.c -o Queue.o
\ No newline at end of file
V0 V2 V5 V1 V3 V6 V4
# 阅读实验源代码
**main.c文件**
在main函数中首先初始化了图和队列,然后调用BreadthFirstSearch函数对图进行广度优先搜索操作,并在全局变量visited中记录下了顶点访问的先后次序,最后销毁了图。
在main函数的后面,分别定义了图的广度优先搜索函数BreadthFirstSearch,以及图的初始化函数和销毁函数。其中,广度优先搜索函数BreadthFirstSearch的函数体还不完整,留给读者完成。
**Graph.h文件**
定义了与图相关的数据结构并声明了相关的操作函数和全局变量。注意,此头文件中还包含了队列模块的头文件Queue.h。
**Queue.h文件**
定义了与队列相关的数据结构并声明了相关的操作函数。
**Queue.c文件**
定义了与队列相关的操作函数。
# 在演示模式下调试项目
**按照下面的步骤调试项目:**
1. 按F7生成项目。
2. 在演示模式下,按F5启动调试项目。程序会在观察点函数的开始位置中断。
3. 重复按F5,直到调试过程结束。
在调试的过程中,每执行“演示流程”窗口中的一行后,仔细观察“可视化数据”窗口内容所发生的变化,理解广度优先搜索的执行过程。“可视化数据”窗口显示的数据信息(如下图所示),包括:
- 对图进行广度优先搜索时产生的顶点访问序列。
- 图的邻接表。
a) 顶点访问标志(0表示顶点未被访问,大于0表示顶点被访问的先后次序,用白色的字体表示)、顶点名称字符串,已访问过的顶点的填充色为灰色,在队列中的顶点使用绿色的边框。
b) 顶点的邻接点(即图中的边、或者弧)。
c) 在调试的过程中,可以看到游标的移动。
- 广度优先搜索使用的队列。
- 在图中,已访问过的顶点的填充色为灰色,并且标出了访问顶点的序号;如果两顶点之间的边是游标指向的当前边,就用红色显示该条边,在调试的过程中,可以看到游标的移动。
![图的广度优先搜索](./img/16_1.png)
![图的广度优先搜索](./img/16_2.png)
# 编写源代码并通过验证
**按照下面的步骤继续实验:**
1. 为BreadthFirstSearch函数编写源代码。注意,尽量使用已定义的局部变量。
2. 按F7生成项目。如果生成失败,根据“输出”窗口中的提示信息修改源代码中的语法错误。
3. 按Alt+F5启动验证。如果验证失败,可以使用“输出”窗口中的“比较”功能,或者在“非演示模式”下按F5启动调试后重复按F10单步调试读者编写的源代码,从而定位错误的位置,然后回到步骤1。
>
**`提示:`**在验证过程中,主要是检测顶点访问序列、以及顶点访问数组生成的是否正确,所以,为了顺利通过验证,请读者在对图进行搜索的同时一定要在全局变量visited中记录下顶点访问的先后次序。
>
# 教师参考答案
访问教师参考答案[domain relative url](engintime/ds-lab/teachers-packet/Lab016.git)
\ No newline at end of file
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论