3270 齐佳欣数据结构课程设计.docx
《3270 齐佳欣数据结构课程设计.docx》由会员分享,可在线阅读,更多相关《3270 齐佳欣数据结构课程设计.docx(22页珍藏版)》请在冰豆网上搜索。
3270齐佳欣数据结构课程设计
上海电力学院
数据结构C++课程设计
题 目:
社会网络分析系统的设计与实现
学生姓名:
齐佳欣
学号:
20103270
院 系:
计算机与信息工程学院
专业年级:
信息安全2010级
2012年 6月29日
一、设计题目
社会网络分析系统的设计和实现
二、需求分析
1)运行环境(软、硬件环境)
软件:
MicrosoftVisualC++
硬件:
处理器:
Intel(R)Pentium(R)CPU
内存(RAM):
2.00GB
2)输入的形式和输入值的范围
1.以字符数据代表社会网络的人员
2.以整形数据代表社会网络人员的关系数(图的边数)
3.输入数值范围(1-100)
3)输出的形式描述
1.输出构建的邻接矩阵
2.输出核心人物、活跃人物、边缘人物,小团体、桥接人物(字符形式)
4)功能描述
1.根据输入的数据构建无向图的连接矩阵,以无向图的边代表两点之间的联系
2.利用度的概念,找出核心人物、活跃人物和边缘人物(规定度数大于所有顶点数一半的为活跃人物,小于一半定点数的为边缘)
3.利用子图,找出小团体的和联系小团体的桥接人。
即在图中找出连通子图,凡是属于不同连通子图的公共点都是桥接点。
4.能查找任何人的交往圈子,任意给出一顶点,找出该顶点所属的连通图,即为该人的交往圈子。
5)测试数据
三、概要设计
1)抽象数据类型定义描述
(对各类的成员及成员函数进行抽象描述,参见书或ppt及实验)
ADTGraphis
Data
存放图中顶点(社会网络人物)的数组
存放图中各顶点之间的边(社会网络人物的关系)的数组
图中人物总数和关系总数
标记数组
Operation
Graph
初始化值:
图中的人数关系数/存放图中的数组/标志顶点访问的数组
动作:
选择操作类型,调用图的创建函数。
createUG
输入:
图中的顶点数(图中的人物数),图中的顶点的边(人员之间的相互联系)
前置条件:
构造函数调用
功能:
创建无向图
输出:
无
后置条件:
无向图建立
Center
输入:
无
前置条件:
无向图已经建立
功能:
找出社会网络的核心人物
输出:
社会网络的核心人物
后置条件:
无
Active
输入:
无
前置条件:
无向图建立
功能:
找出社会网络的活跃人物
输出:
社会网络的活跃人物
后置条件:
无
Border
输入:
无
前置条件:
无向图的建立
功能:
找出社会网络的边缘人物
输出:
社会网络的边缘人物
后置条件:
无
PrintGraph
输入:
无
前置条件:
无向图建立
功能:
输出邻接矩阵
输出:
输出邻接矩阵
后置条件:
无
DFSTraverse
输入:
无
前置条件:
无向图的建立,对标志数组进行初始化为0
功能:
从指定的顶点开始深度遍历
输出:
深度遍历序列,找出指定点的交往圈子
后置条件:
无
DFS
输入:
无
前置条件:
无向图的建立,重新对数组进行置0处理
功能:
从指定的顶点开始进行深度遍历
输出:
输出连通图的序列
后置条件:
对访问过的顶点置1
Group
输入:
无
前置条件:
无向图的建立,已对访问过的顶点
功能:
从指定的顶点开始进行深度遍历
输出:
已标记为1的顶点
后置条件:
无
2)功能模块设计(如主程序模块设计)
1.主程序模块:
连接各种功能的子模块,完成需要的操作和实现的功能。
2.社会网络构建模块:
按照相关步骤和要求构建无向图。
3.核心人物模块:
根据用户的输入,构建的相关的无向图,由度的概念程序计算出网络的核心人物。
4.活跃人物模块:
根据用户的输入,构建相关的无向图,由度的概念程序计算出网络的活跃人物。
5.边缘人物模块:
根据用户的输入,构建相关的无向图,由度的概念程序计算出网络的边缘人物。
6.小团体模块:
根据用户的输入,构建相关的无向图,由深度遍历程序输出遍历的序列即为小团体。
3)模块层次调用关系图
四、详细设计
实现概要设计中定义的所有的类的定义及类中成员函数,并对主要的模块写出伪码算法。
1)对类的定义:
template
classGraph
{
public:
Graph(Ta[],intn,inte);//构造函数,a[]表示数组,表示顶点的个数,e表示边数
voidcenter(intn);//声明核心人物函数
voidprintGraph();//输出邻接矩阵
voidactive(intn);//活跃人物函数
voidDFSTraverse(intv);//对图进行深度优先遍历,找出某一点所属的小团体
voidborder(intn);//边缘人物函数
voidDFS(intv);//对图的连通子图进行深度优先遍历,找出小团体
voidgroup(intn);找出两个小团体的桥接人物
private:
Tvertex[maxsize];//顶点数组
intarc[maxsize][maxsize];//边数
intvertexNum,arcNum;//定点数,边数
voidcreateUG(Ta[],intn,inte);//构建无向图
int*visited;//设置标志数组
};
成员函数:
1)核心人物,活跃人物,边缘人物
template
voidGraph:
:
center(intn)
{vertexNum=n;
inti,j;
intk=0;
intdm[maxsize]={0};
for(i=0;ifor(j=0;jdm[i]+=arc[i][j];
///////////////////////////////
intx=dm[0];
for(i=0;i{
if(dm[i]>x)
{
x=dm[i];
k=i;
}
}
cout<<"该社会网络的核心人物是:
"<}
////////////////////////
template
voidGraph:
:
active(intn)
{vertexNum=n;
inti,j;
intdm[maxsize]={0};
for(i=0;ifor(j=0;jdm[i]+=arc[i][j];
cout<<"活跃人物有:
";
for(i=0;i{
if(dm[i]>vertexNum/2)//规定一个顶点的度数大于定点数一半的即为活跃人物
{
cout<}
}
}
template
voidGraph:
:
border(intn)
{vertexNum=n;
inti,j;
intdm[maxsize]={0};
for(i=0;ifor(j=0;jdm[i]+=arc[i][j];
cout<<"边缘人物有:
";
for(i=0;i{
if(dm[i]{cout<}
}
2)深度优先遍历
i)找出小团体间的桥接点
ii)找出某一点所属的小团体
template
voidGraph:
:
DFSTraverse(intv)//深度优先遍历图
{
cout<<"该人员是"<cout<<"与该人员交往的圈子是:
";
for(intj=0;j{
if(arc[v-1][j]==1||arc[j][v-1]==1)
//DFSTraverse(j)
cout<}
}////////////////////////////////团体查找
template
voidGraph:
:
DFS(intv)//深度优先遍历图(无向图)
{
if(v==0)//判断是不是初始使用而不是递归调用是的话初始化顶点标记矩阵,代表没有访问过,代表访问过
{
for(inti=0;ivisited[i]=0;
//visited[vertexNum]=999;//表示顶点数的标记信息显示到此为止
/*for(intm=0;mfor(intn=0;nif(n==vertexNum-1)
{
cout<cout<}
else
cout<DFS
(1);
}
else
{
if(visited[v-1]==0)//判断当前结点是否被访问过,没有访问过才继续进行操作
{
visited[v-1]=1;//立刻将该结点置为访问过
cout<for(inti=v-1;iif(arc[v-1][i]==1)//判断两个结点之间是否连通,连通则进入其中进行遍历
DFS(i+1);
else
;
}
else
;
}
}
//////////////////
template
voidGraph:
:
group(intn)
{
visited[n]=1;
for(intj=0;j{if(visited[j]==1)
{cout<if(arc[n][j]==1&&visited[j]==0)
{group(j);}
}
}
五、调试分析
包括调试过程中遇到的问题及解决的方法、算法的时间空间复杂性分析、经验体会。
1)遇到问题
Q1.首先这个社会网络是构建有向图还是无向图?
K1.最终决定构建无向图,理由是,若构建有向图是表示两人间的相互关系,无向图是表示这两人人之间存在关系,我认为有向图可用于通讯录,用在社会网络分析图的构建上不是很妥当。
Q2.标志数组已在构造函数中进行初始化,为什么还要在成员函数对各个顶点重新赋值?
K2.这主要是限于本题目的要求,因为深度优先遍历调用次数大于两次,已标记过的顶点会对后续调用产生影响,所以需对其重新赋初值。
Q3.如何查找小团体?
K3.根据子图的定义,从某一顶点开始进行深度优先遍历,所得的连通子图序列即为该点所属的小团体。
Q4.如何查找小团体间的桥接点?
K4.所谓的桥接点,即属于不同小团体间的公共点。
以某一点开始对图深度优先遍历,得到一个连通子图,再以另一点开始进行深度优先遍历,输出已标志为1的顶点,即为两个小团体的公共点。
2)算法时间空间复杂性分析
答:
深度优先遍历的时间复杂度O(n2)
输出遍历的时间复杂度为O(n2)
3)经验体会
由于自身能力原因,感觉这道题目还是有一定难度的。
题目要求中的前两问还能做出,在寻找小团体的桥接点和某一点所属的小团体中,做了很多尝试方法,结果都不尽人意,最后还是经过的老师的指点和讲解,才解得出来。
主要是由于对图的概念掌握不够深刻,尤其是连通子图的深度优先遍历,并不是简单地对整个图进行遍历,这一点最开始并没有注意到。
对连通子图进行深度优先遍历时,首先还是要判断这一点是否有下一个连接点,如果有的话,那么继续进行遍历,如果没有,那么到此结束。
而如果对整个图(可以是连通图,也可以是不连通的图)进行深度优先遍历时,还需要加上如下语句,
for(intj=0;j{
if(arc[v][j]==1&&visited[j]==0)
DFSTraverse(j,visited);
}
才能将所有的点都遍历一个遍,并且保证不重复遍历。
总之经过这次课程设计,发现问题,思考产生问题的原因,不断改进,最终解决问题这一过程对图这一类型的数据结构有了更加深刻的理解,加深了对其应用的认识。
六用户使用说明
详细列出每一步的操作说明。
1.用户输入社会网络人物的总数
2.输入社会网络人物的名称
3.输入社会网络人物的总边数
4.选择是否要知道某个人的交往圈子(1表示是,0表示否)
5.输入要知道的人的交往圈子的数字代码
6.选择是否要知道该社会网络人物的核心人物、活跃人物、边缘人物。
七、测试结果
八、附录:
程序设计源代码
#include
usingnamespacestd;
constintmaxsize=100;
template
classGraph
{
public:
Graph(Ta[],intn,inte);//构造函数,a[]表示数组,表示顶点的个数,e表示边数
voidcenter(intn);//声明核心人物函数
voidprintGraph();//输出邻接矩阵
voidactive(intn);//活跃人物函数
voidDFSTraverse(intv);//对图进行深度优先遍历,找出某一点所属的小团体
voidborder(intn);//边缘人物函数
voidDFS(intv);//对图的连通子图进行深度优先遍历,找出小团体
voidgroup(intn);//找出两个小团体的桥接人物
private:
Tvertex[maxsize];//顶点数组
intarc[maxsize][maxsize];//边数
intvertexNum,arcNum;//定点数,边数
voidcreateUG(Ta[],intn,inte);//构建无向图
int*visited;//设置标志数组
};
//////////////////////构造函数
template
Graph:
:
Graph(Ta[],intn,inte)
{
visited=newint[vertexNum];//对标志数组进行初始化
for(inti=0;ivisited[i]=0;
intkind;
cout<<"该系统创建的图类型为:
"<cout<<"-----1.无向图-----"<cin>>kind;
switch(kind)
{
case1:
createUG(a,n,e);break;
default:
cout<<"输入数值错误"<}
}
/////////////////构建无向图
template
voidGraph:
:
createUG(Ta[],intn,inte)
{//创建无向图
vertexNum=n;//顶点数
arcNum=e;//边数
inti,j,k;
for(i=0;ivertex[i]=a[i];
for(i=0;ifor(j=0;jarc[i][j]=0;
for(k=0;k//依次输入每一条边,并修改邻接矩阵的相应元素
{
cout<<"请输入第"<顶点1顶点2):
";
cin>>i>>j;//边依附的两个顶点的序号
arc[i-1][j-1]=1;//置有边标志
arc[j-1][i-1]=1;
}
}
////////////////////////////////该网络的核心人物,活跃人物,边缘人物
template
voidGraph:
:
center(intn)
{vertexNum=n;
inti,j;
intk=0;
intdm[maxsize]={0};
for(i=0;ifor(j=0;jdm[i]+=arc[i][j];
///////////////////////////////
intx=dm[0];
for(i=0;i{
if(dm[i]>x)
{
x=dm[i];
k=i;
}
}
cout<<"该社会网络的核心人物是:
"<}
////////////////////////
template
voidGraph:
:
active(intn)
{vertexNum=n;
inti,j;
intdm[maxsize]={0};
for(i=0;ifor(j=0;jdm[i]+=arc[i][j];
cout<<"活跃人物有:
";
for(i=0;i{
if(dm[i]>vertexNum/2)//规定一个顶点的度数大于定点数一半的即为活跃人物
{
cout<}
}
}
template
voidGraph:
:
border(intn)
{vertexNum=n;
inti,j;
intdm[maxsize]={0};
for(i=0;ifor(j=0;jdm[i]+=arc[i][j];
cout<<"边缘人物有:
";
for(i=0;i{
if(dm[i]{
cout<}
}
}
template
voidGraph:
:
printGraph()
{//输出邻接矩阵
inti,j;
for(i=0;i{
for(j=0;jcout<cout<}
}
//////////////////////////查找任意人的交往圈子
template
voidGraph:
:
DFSTraverse(intv)//深度优先遍历图
{
cout<<"该人员是"<cout<<"与该人员交往的圈子是:
";
for(intj=0;j{
if(arc[v-1][j]==1||arc[j][v-1]==1)
//DFSTraverse(j)
cout<}
}////////////////////////////////团体查找
template
voidGraph:
:
DFS(intv)//深度优先遍历图(无向图)
{
if(v==0)//判断是不是初始使用而不是递归调用是的话初始化顶点标记矩阵,代表没有访问过,代表访问过
{
for(inti=0;ivisited[i]=0;
//visited[vertexNum]=999;//表示顶点数的标记信息显示到此为止
/*for(intm=0;mfor(intn=0;nif(n==vertexNum-1)
{
cout<cout<}
else
cout<DFS
(1);
}
else
{
if(visited[v-1]==0)//判断当前结点是否被访问过,没有访问过才继续进行操作
{
visited[v-1]=1;//立刻将该结点置为访问过
cout<for(inti=v-1;iif(arc[v-1][i]==1)//判断两个结点之间是否连通,连通则进入其中进行遍历
DFS(i+1);
else
;
}
else
;
}
}
//////////////////
template
voidGraph:
:
group(intn)
{
visited[n]=1;
for(intj=0;j{if(visited[j]==1)
{
cout<}
if(arc[n][j]==1&&visited[j]==0)
{
group(j);
}
}
}
///////////////////////////////////////////////