中南大学数据结构拓扑实验报告.docx
- 文档编号:10831380
- 上传时间:2023-02-23
- 格式:DOCX
- 页数:19
- 大小:630.72KB
中南大学数据结构拓扑实验报告.docx
《中南大学数据结构拓扑实验报告.docx》由会员分享,可在线阅读,更多相关《中南大学数据结构拓扑实验报告.docx(19页珍藏版)》请在冰豆网上搜索。
中南大学数据结构拓扑实验报告
目录
一、问题描述……………………………3
二、基本要求……………………………3
三、数据结构的设计……………………3
四、软件模块结构图……………………4
五、程序流程图…………………………4
六、源程序………………………………5
七、调试分析……………………………12
八、测试数据……………………………13
九、用户使用手册………………………15
十、心得体会……………………………15
一、问题描述
拓扑排序问题
问题描述:
采用适当的存储结构,实现有向网的存储,建立,输入,显示,以及实现对有向无环图的拓扑有序序列的输出。
二、基本要求
(1)熟练掌握图的基本存储方法;
(2)熟练掌握图的深度优先和广度优先搜索方法;
(3)掌握AOV网和拓扑排序算法;
(4)掌握AOE网和关键路径。
三、数据结构的设计
设计思想:
有向图可以拓扑排序的条件是:
图中没有环。
简要方法:
⑴从图中选择一个入度为0的点加入拓扑序列。
⑵从图中删除该结点以及它的所有出边(即与之相邻点入度减1)。
反复执行这两个步骤,直到所有结点都已经进入拓扑序列。
详细分析:
为实现对无权值有向图进行拓扑排序,输出拓扑序列,先考虑如何存储这个有向图。
拓扑排序的过程中要求找到入度为0的顶点,所以要采用邻接表来存储有向图,而要得到邻接表,则先要定义有向图的邻接矩阵结构,再把邻接矩阵转化成邻接表。
在具体实现拓扑排序的函数中,根据规则,当某个顶点的入度为0(没有前驱顶点)时,就将此顶点输出,同时将该顶点的所有后继顶点的入度减1,为了避免重复检测入度为0的顶点,设立一个栈St,以存放入度为0的顶点。
MFC的创作:
参照了教材,使用MicrosoftVisualStudio,把图形界面的对应方框进行输入输出处理。
四、软件模块结构图
五、程序流程图
按照流程图的具体分析如下:
1、图像输入:
建立一个有向无环图,要考虑到输入的方式尽量方便全面,采用输入弧的方式,输入每条弧的链接的两个结点。
2、判断图是不是有向无环图:
完成输入后,队列应该是满的。
选取入度为零的结点,入队列,调整数组,循环进行。
如果队列不满,则输入的图不符合要求,应该重新输入。
3、拓扑排序:
现在所得的弧是有向无环,再循环出队列,按照队列固有的顺序进行输出即可,排序完成。
六、源程序
头文件:
//jkl.h:
PROJECT_NAME应用程序的主头文件
//
#pragmaonce
#ifndef__AFXWIN_H__
#error"在包含此文件之前包含“stdafx.h”以生成PCH文件"
#endif
#include"resource.h"//主符号
//CjklApp:
//有关此类的实现,请参阅jkl.cpp
//
classCjklApp:
publicCWinApp
{
public:
CjklApp();
//重写
public:
virtualBOOLInitInstance();
//实现
DECLARE_MESSAGE_MAP()
};
structnode
{
intadjvex;
node*next;
};
structgraph
{
intvexter;
intin;
node*firstedge;
};
typedefstruct
{
int*base;
int*top;
intstacksize;
}sqstack;
externCjklApptheApp;
源文件:
//jklDlg.cpp:
实现文件
//
#include"stdafx.h"
#include"jkl.h"
#include"jklDlg.h"
#include"malloc.h"
#include"stdio.h"
#include"WzdSplash.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#endif
graphinDegree[50];
//用于应用程序“关于”菜单项的CAboutDlg对话框
voidinitstack(sqstack&S)
{
S.base=(int*)malloc(sizeof(int));
S.top=S.base;
S.stacksize=50+1;
}
voidcreateadlist(inttab[],graphinDegree[],intn,inte)//创建邻接链表
{
inti,k,j;
intM=0;
node*q;
for(i=1;i<=n;i++)
{
inDegree[i].vexter=i;
inDegree[i].in=0;
inDegree[i].firstedge=NULL;
}
for(k=1;k<=e;k++)
{
i=tab[M];
j=tab[++M];
printf("%d%d",i,j);
M++;
inDegree[j].in++;
q=(node*)malloc(sizeof(structnode));
q->adjvex=j;
q->next=inDegree[i].firstedge;
inDegree[i].firstedge=q;
}
}
boolTopoSort(graphinDegree[],intn,CString&str)
{
inti,v,count=0;
sqstackS;
node*p;
initstack(S);
for(i=1;i<=n;i++)
if(inDegree[i].in==0)
*S.top++=i;
while(S.top!
=S.base)
{
v=*--S.top;
str.AppendFormat(_T("%d"),v);
str.AppendFormat(_T(""));
count++;
p=inDegree[v].firstedge;
while(p!
=NULL)
{
inDegree[p->adjvex].in--;
if(inDegree[p->adjvex].in==0)
*S.top++=p->adjvex;
p=p->next;
}
}
if(count { returnfalse;} else { returntrue;} } classCAboutDlg: publicCDialog { public: CAboutDlg(); //对话框数据 enum{IDD=IDD_ABOUTBOX}; protected: virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDV支持 //实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg: : CAboutDlg(): CDialog(CAboutDlg: : IDD) { } voidCAboutDlg: : DoDataExchange(CDataExchange*pDX) { CDialog: : DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg,CDialog) END_MESSAGE_MAP() //CjklDlg对话框 CjklDlg: : CjklDlg(CWnd*pParent/*=NULL*/) : CDialog(CjklDlg: : IDD,pParent) { m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME); } voidCjklDlg: : DoDataExchange(CDataExchange*pDX) { CDialog: : DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CjklDlg,CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_BUTTON1,&CjklDlg: : OnBnClickedButton1) END_MESSAGE_MAP() //CjklDlg消息处理程序 BOOLCjklDlg: : OnInitDialog() { CDialog: : OnInitDialog(); //将“关于...”菜单项添加到系统菜单中。 //IDM_ABOUTBOX必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX<0xF000); CMenu*pSysMenu=GetSystemMenu(FALSE); if(pSysMenu! =NULL) { CStringstrAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if(! strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu); } } //设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动 //执行此操作 SetIcon(m_hIcon,TRUE);//设置大图标 SetIcon(m_hIcon,FALSE);//设置小图标 CWzdSplashwndSplash;//´´½¨Æô¶¯´°¿ÚÀàµÄʵÀý wndSplash.Create(IDB_BITMAP1); wndSplash.CenterWindow(); wndSplash.UpdateWindow();//sendWM_PAINT Sleep(1500); wndSplash.DestroyWindow();//Ïú»Ù³õʼ»Ãæ´°¿Ú //ÒÔÉÏÊÇʵÏÖÎļþµÄ´úÂë//TODO: 在此添加额外的初始化代码 returnTRUE;//除非将焦点设置到控件,否则返回TRUE } voidCjklDlg: : OnSysCommand(UINTnID,LPARAMlParam) { if((nID&0xFFF0)==IDM_ABOUTBOX) { CAboutDlgdlgAbout; dlgAbout.DoModal(); } else { CDialog: : OnSysCommand(nID,lParam); } } //如果向对话框添加最小化按钮,则需要下面的代码 //来绘制该图标。 对于使用文档/视图模型的MFC应用程序, //这将由框架自动完成。 voidCjklDlg: : OnPaint() { if(IsIconic()) { CPaintDCdc(this);//用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND,reinterpret_cast //使图标在工作区矩形中居中 intcxIcon=GetSystemMetrics(SM_CXICON); intcyIcon=GetSystemMetrics(SM_CYICON); CRectrect; GetClientRect(&rect); intx=(rect.Width()-cxIcon+1)/2; inty=(rect.Height()-cyIcon+1)/2; //绘制图标 dc.DrawIcon(x,y,m_hIcon); } else { CDialog: : OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSORCjklDlg: : OnQueryDragIcon() { returnstatic_cast } voidCjklDlg: : OnBnClickedButton1() { CEdit*text1; CEdit*text2; CEdit*text3; CEdit*text4; CStringstr,str2,str3,str4,str5; //charC[1000]; text1=(CEdit*)GetDlgItem(IDC_EDIT3); text2=(CEdit*)GetDlgItem(IDC_EDIT1); text3=(CEdit*)GetDlgItem(IDC_EDIT2); text4=(CEdit*)GetDlgItem(IDC_EDIT4); text1->GetWindowText(str); text2->GetWindowText(str2); text3->GetWindowText(str3); intv,e; v=_ttoi(str2); e=_ttoi(str3); CStringstr1; intj=0,input[1000]; memset(input,0,sizeof(input)); intlen=str.GetLength(); for(inti=0;i { if(str[i]==''){j++;continue;} input[j]*=10; input[j]+=str[i]-'0'; } j++; boolflag=false; createadlist(input,inDegree,v,e); flag=TopoSort(inDegree,v,str4); if(! flag) { str5.Format(_T("Therearecycles! ")); text4->SetWindowText(str5); } else { text4->SetWindowText(str4); } /*for(inti=0;i str5.AppendFormat(_T("%d"),input[i]); str5.AppendFormat(_T("")); } text4->SetWindowText(str5);*/ //TODO: 在此添加控件通知处理程序代码 } 七、调试分析 在调试时主要遇到以下问题: 八、测试数据 进入界面: 运行界面: 测试数据: 第一个例子: 顶点数是6,边数是5,点的指向分别是: 1-2,2-3,2-4,4-5,3-6 结果是无环有序线性输出 第二个例子: 顶点数: 5,边数: 5,点的指向分别是: 1-2,2-3,3-4,4-5,5-2 结果是有环输出,不排序 九、用户使用手册 打开 这一个exe运行,进入到操作界面后,按照拓扑排序的原理输入符合的顶点数与边数,在第三个方框中,用空格对每条边的起点与末点分隔开,用空格把不同的两条边分隔开,点击确定,就会有结果输出。 允许重新在输入方框直接修改再按确定得到结果。 十、心得体会 本次试验通过对有向图进行拓扑排序,我了解了有向图的邻接矩阵和邻接表的存储结构以及它们之间的相互转化,更重要的的是学会了对有向图的拓扑排序算法,其中也将之前学过的栈结合起来,巧妙的找到了一个拓扑序列,可不足的是,该算法只能找到这一条拓扑序列,但是我相信通过完成了这次试验后我会改进算法而能将图的所有的拓扑序列找出来。 另外创新的利用MFC制造图形界面,美观简洁方便使用程序,放下了固有的DOS黑底界面,这大胆的尝试让我学习到好多课本外的知识,获益良多,使知识更为活用有价值。 通过这段时间的课程设计,我认识到数据结构是一门比较难的课程。 需要多花时间上机练习。 这次的程序训练培养了我实际分析问题、编程和动手能力,使我掌握了程序设计的基本技能,提高了我适应实际,实践编程的能力。 总的来说,这次课程设计让我获益匪浅,对数据结构也有了进一步的理解和认识。 参考文献 [1]严蔚敏,吴伟民编著.数据结构(C语言版)北京: 清华大学出版社,2007. [2]谭浩强编著C程序设计(第三版)——北京: 清华大学出版社,2008 [3]刘振安,孙忱,刘燕君编著C程序设计课程设计——北京: 机械工业出版社,2007
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 中南 大学 数据结构 拓扑 实验 报告