社会网络分析系统的设计和实现数据结构课程设计学士学位论文.docx
《社会网络分析系统的设计和实现数据结构课程设计学士学位论文.docx》由会员分享,可在线阅读,更多相关《社会网络分析系统的设计和实现数据结构课程设计学士学位论文.docx(34页珍藏版)》请在冰豆网上搜索。
![社会网络分析系统的设计和实现数据结构课程设计学士学位论文.docx](https://file1.bdocx.com/fileroot1/2023-7/22/283833a9-0ac8-42b3-846d-1ddb3f3c24f3/283833a9-0ac8-42b3-846d-1ddb3f3c24f31.gif)
社会网络分析系统的设计和实现数据结构课程设计学士学位论文
上海电力学院
数据结构(C++)课程设计
题 目:
综合实验16
社会网络分析系统的设计和实现(*)
目录
一、设计题目1
二、需求分析1
1)运行环境(软、硬件环境)1
2)输入的形式和输入值的范围1
3)输出的形式描述1
4)功能描述1
5)测试数据2
三、概要设计2
1)抽象数据类型定义描述2
2)功能模块设计(如主程序模块设计)5
3)模块层次调用关系图5
四、详细设计6
五、调试分析12
Ø问题&改进&补充12
Ø算法的时间空间复杂性分析14
Ø心得体会14
六、测试结果15
七、附录:
程序设计源代码16
1、设计题目
社会网络分析系统的设计和实现
二、需求分析
1)运行环境(软、硬件环境)
软件:
MicrosoftVisualC++6.0
硬件:
能运行MicrosoftVisualC++6.0的硬件平台
如CPU:
Intel酷睿i33217U;内存4G;操作系统Windows7
2)输入的形式和输入值的范围
数据类型:
整型(int)、字符型(char)
范围:
1.总人数(1~100)
2.人员名称(A~Z)
3.人员数字代码(1~100)
4.关系总数(1~100)
5.某条关系(人员数字代码人员数字代码权值)注:
权值(1~100)即email数据
举例:
总人数8个、人员名称ABCDEFGH、人员数字代码12345678、关系总数15条、具体某一条关系129。
3)输出的形式描述
1.该社会网络的邻接矩阵
2.该社会网络中的核心人物、活跃人物、边缘人物
3.该社会网络中的小团体、桥接人物
4.查找任何人的交往圈子
4)功能描述
1.对email数据进行预处理,利用数据结构课程中图中的理论,建立社会网络的邻接矩阵。
2.利用度的概念,找出社会网络中核心人物、活跃人物和边缘人物。
3.利用子图概念,分析社会网络的结构,找出小团体和联系小团体的桥接人物。
4.能查找任何人的交往圈子。
5)测试数据
三、概要设计
1)抽象数据类型定义描述
(对各类的成员及成员函数进行抽象描述,参见书或ppt及实验)
ADT Mgraph is
Data
存放图中社会网络人物的一维数组vertex[maxsize]
存放图中社会网络人物的关系的二维数组arc[maxsize][maxsize]
图中人物总数vertexnum和关系总数,arcnum
标志数组visited
Operation
◆Mgraph(构造函数)
初始化值:
社会网络中a[]人员名称,n总人数,e总关系数;标志顶点访问的数组visited[i]置0。
动作:
将键盘输入的值带入,调用有向网的创建函数CreateHW。
◆CreateHW(创建有向网)
输入:
图的人数和关系数、存放图中人的数组、存放图中关系的数组
前置条件:
构造函数调用
功能:
创建有向网
输出:
无
后置条件:
有向网建立
◆PrintGraph(输出邻接矩阵)
输入:
无
前置条件:
有向网已经建立
功能:
输出邻接矩阵
输出:
邻接矩阵
后置条件:
无
◆Centre(核心人物)
输入:
无
前置条件:
有向网已经建立,设定核心人物的域值yu=20
功能:
找出社会网络的核心人物(计算每个顶点的入度,找度数大于域值的人物)
输出:
若找到则输出社会网络的核心人物,没有找到则输出“无”。
后置条件:
无
◆Huoyue(活跃人物)
输入:
无
前置条件:
有向网已经建立,设定活跃人物的域值yu=10
功能:
找出社会网络的活跃人物(计算每个顶点的出度,找度数大于域值的人物)
输出:
若找到则输出社会网络的活跃人物,没有找到则输出“无”。
后置条件:
无
◆Bianyuan(边缘人物)
输入:
无
前置条件:
有向网已经建立,设定边缘人物的域值yu=5
功能:
找出社会网络的边缘人物(计算每个顶点的出入度之和,找度数小于域值的人物)
输出:
若找到则输出社会网络的边缘人物,没有找到则输出“无”。
后置条件:
无
◆quanzi(交往圈子)
输入:
输入一个人员的数字代码(用于查找该人员的交往圈子)
前置条件:
有向网已经建立
功能:
查找交往圈子(与指定人物之间有边的人物就是与该人物有联系的,这些人就构成了一个交往圈子)。
输出:
输出指定人物的交往圈子
后置条件:
无
◆ADD(计算人员两两间的关系数)
输入:
无
前置条件:
有向网已经建立,给出两个人物的数字代码
功能:
计算指定人员两两间的联系数并返回(为查找小团体、桥接人做准备)
输出:
返回指定人员两两间的联系数
后置条件:
无
◆BY(返回边缘人物数字代码)
输入:
无
前置条件:
有向网已经建立
功能:
找边缘人物并返回该人物数字代码(为查找小团体、桥接人做准备)
输出:
返回边缘人物的数字代码
后置条件:
无
◆DFS(小团体)
输入:
无
前置条件:
有向网、ADD函数、BY函数都已经建立,初始化顶点标记矩阵(全部置0)
功能:
查找小团体,从指定的顶点开始进行深度优先遍历(如果当前人物没有被访问过,并且也不是边缘人物,输出该人物;再从该人物开始进行深度遍历,如果找到与该人物交往密切的人物则输出,继续找下一个)
输出:
输出小团体
后置条件:
对访问过的顶点置1
◆DFS2(桥接人)
输入:
无
前置条件:
有向网、ADD函数、BY函数都已经建立
功能:
查找桥接人,从指定的顶点开始进行深度优先遍历
输出:
两个小团体中,有联系,但没有达到域值的人物
后置条件:
无
endADTMgraph
2)功能模块设计(如主程序模块设计)
1.主程序模块:
连接各种功能子模块,完成程序的基本操作实现功能
2.构造社会网络模块:
按照要求构建有向网
3.输出邻接矩阵模块:
根据用户输入的社会网络,输出该网络图的邻接矩阵
4.核心人物模块:
根据用户输入的社会网络,计算得出该社会网络中的核心人物
5.活跃人物模块:
根据用户输入的社会网络,计算得出该社会网络中的活跃人物
6.边缘人物模块:
根据用户输入的社会网络,计算得出该社会网络中的边缘人物
7.交往圈子模块:
根据用户输入的社会网络,计算得出该网络中指定人物的交往圈子
8.人物两两联系数模块:
根据用户输入的社会网络,返回指定人员两两间的联系数
9.判断边缘人物模块:
根据用户输入的社会网络,返回边缘人物的数字代码
10.小团体模块:
根据用户输入的社会网络,深度优先遍历得出该网络中的所有小团体
11.桥接人物模块:
根据用户输入的社会网络,深度优先遍历得出小团体间的桥接人物
3)模块层次调用关系图
4、详细设计
实现概要设计中定义的所有的类的定义及类中成员函数,并对主要的模块写出伪码算法。
#include
#include
#include
constintmaxsize=100;
constintINFINITY=0;//最大值无穷
定义一个Mgraph类,用来实现基本功能:
构造函数初始化值,根据用户输入的社会网络图构建有向网(邻接矩阵存储形式),查找该社会网络中的核心人物、活跃人物、边缘人物、小团体、桥接人物,查找任何人的交往圈子。
template
classMgraph
{
public:
Mgraph(Ta[],intn,inte);//构造函数,a[]结点数组,n顶点个数,e边数
voidPrintGraph();//输出邻接矩阵
voidcentre(intn);//核心人物成员函数
voidhuoyue(intn);//活跃人物成员函数
voidbianyuan(intn);//边缘人物成员函数
voidquanzi(intv);//查找交往圈子函数
intADD(ints,intt);//计算人员两两间联系数
intBY(intn);
voidDFS(intv,intn);//查找小团体函数(深度优先遍历)
voidDFS2(intv,intn);//查找桥接人函数(深度优先遍历)
private:
Tvertex[maxsize];//存放顶点
intarc[maxsize][maxsize];//存放边
intvertexnum,arcnum;//顶点数,边数
voidCreateHW(Ta[],intn,inte);//构建有向网
int*visited;
};
————————Mgraph构造函数————————
初始化值:
社会网络中a[]人员名称,n总人数,e总关系数;标志顶点访问的数组visited[i]置0;调用有向网的创建函数CreateHW。
template
Mgraph:
:
Mgraph(Ta[],intn,inte)
{visited=newint[vertexnum];
for(inti=0;ivisited[i]=0;
CreateHW(a,n,e);//创建
}
//————————CreateHW构建有向网————————
将用户输入的值带入,并完成存储:
人物名称放入一维数组vertex[i],人物间的Email发送数(权值)放入二维数组arc[i-1][j-1]。
template
voidMgraph:
:
CreateHW(Ta[],intn,inte)
{intw;//权值
vertexnum=n;//顶点数
arcnum=e;//边数
inti,j,k;
cout<<"注意!
请将人名对应到数字代码输入"<cout<<"输入格式为:
人员1人员2权值"<for(i=0;ivertex[i]=a[i];//顶点数组赋初值(放入一维数组)
for(i=0;ifor(j=0;jarc[i][j]=0;
for(k=0;k{//依次输入每一条边,并修改邻接矩阵的相应元素
cout<<"请输入第"<";
cin>>i>>j>>w;//边依附的两个顶点的序号
arc[i-1][j-1]=w;//置有边标志,存放权值
}
}
//———————PrintGraph输出—————————
通过二重循环输出社会网络对应的邻接矩阵存储图
template
voidMgraph:
:
PrintGraph()
{//输出邻接矩阵
inti,j;
for(i=0;i{for(j=0;jcout<cout<}
}
//——————centre核心人物————————
若人物收到的Email总数大于20封,我认为就是核心人物,所以我设置了域为20,centre函数要完成的功能是找入度大于域值的人物,并输出。
template
voidMgraph:
:
centre(intn)
{vertexnum=n;
inti,j,count=0;
intx[maxsize]={0};
for(i=0;ifor(j=0;jx[i]+=arc[j][i];//x[j]存放入度数
cout<<"—→核心人物是:
";
intyu=20;//找度数大于域值的人物,域=20
for(i=0;i{if(x[i]>yu)
{cout<count++;
}
}
if(count==0){cout<<"无";}
cout<}
//————————huoyue活跃人物————————
若人物发出的Email总数大于10封,我认为就是活跃人物,所以我设置了域为10,huoyue函数要完成的功能是找出度大于域值的人物,并输出。
template
voidMgraph:
:
huoyue(intn)
{vertexnum=n;
inti,j,count=0;
inty[maxsize]={0};
for(i=0;ifor(j=0;jy[i]+=arc[i][j];//y[i]存放出度数
cout<<"—→活跃人物是:
";
intyu=10;//找度数大于域值的人物,域=10
for(i=0;i{if(y[i]>yu)
{cout<count++;
}
}
if(count==0){cout<<"无";}
cout<}
//————————bianyuan边缘人物————————
若人物收到和发出的Email总数小于5封,我认为就是边缘人物,所以我设置了域为5,bianyuan函数要完成的功能是找入度与出度之和小于域值的人物,并输出。
template
voidMgraph:
:
bianyuan(intn)
{vertexnum=n;
inti,j,count=0;
intz[maxsize]={0};
for(i=0;ifor(j=0;jz[i]=z[i]+arc[i][j]+arc[j][i];//z[i]存放入度+出度之和
cout<<"—→边缘人物是:
";
intyu=5;//找度数小于域值的人物,域=5
for(i=0;i{if(z[i]{cout<count++;
}
}
if(count==0){cout<<"无";}
cout<}
//————————quanzi查找交往圈子————————
根据用户输入的一个人员的数字代码,查找该人员的交往圈子,我认为与指定人物之间有边的人物就是与该人物有联系的,这些人就构成了一个交往圈子。
template
voidMgraph:
:
quanzi(intv)
{
intcount=0;
cout<<"—→"<";
for(intj=0;j{if(arc[v-1][j]!
=INFINITY||arc[j][v-1]!
=INFINITY)//交往圈子:
与指定人物之间有边就算
{cout<count++;
}
}
if(count==0){cout<<"无";}
cout<}
//——————ADD计算人员间两两间联系数————————
计算指定人员两两间的联系数并返回(为查找小团体、桥接人做准备)
template
intMgraph:
:
ADD(ints,intt)
{inttemp;
if(s>t)
{temp=s;s=t;t=temp;}
elsereturn(arc[s][t]+arc[t][s]);
}
//—————BY查找小团体中用来判断边缘人物——————
找边缘人物并返回该人物数字代码(为查找小团体、桥接人做准备)
template
intMgraph:
:
BY(intn)
{inti,j,count=0;
intz[maxsize]={0};
for(i=0;ifor(j=0;jz[i]=z[i]+arc[i][j]+arc[j][i];//z[i]存放入度+出度之和
intyu=5;//域=5
for(i=0;i{
if(z[i]{
return(i);
count++;
}
}
if(count==0)
return(99);
}
//————————DFS查找小团体————————
查找小团体,从指定的顶点(我设置的是0也就是第一个人)开始进行深度优先遍历(如果当前人物A没有被访问过,并且也不是边缘人物,输出该人物A;再从该人物A开始进行深度遍历,如果找到与该人物交往密切的人物B则输出,再从B开始继续找下一个),并且在查找过程中输出小团体成员。
template
voidMgraph:
:
DFS(intv,intn)//v控制递归n为总人数
{
if(v==0)//如果是第一次使用
{
for(intk=0;kvisited[k]=0;//初始化顶点标记矩阵(全部置0代表没有访问过)
DFS(v+1,n);//利用递归算法重复调用深度优先遍历DFS
}
else
{
if(visited[v-1]==0)//如果当前人物没有被访问过
{
if(v-1!
=BY(n))//并且也不是边缘人物
{intyu=10;//域值
cout<visited[v-1]=1;//将该结点置为访问过!
for(intk=0;k{
if(ADD(v-1,k)>yu)//如果两个结点之间交往密切
{DFS(k+1,n);}//找下一个
}
cout<<",";
DFS(v+1,n);
}
elseDFS(v+1,n);
}
}
}
//————————DFS2查找桥接人————————
查找桥接人,两个小团体中,有联系,但没有达到域值的人物。
从指定的顶点开始进行深度优先遍历
template
voidMgraph:
:
DFS2(intv,intn)//v控制递归n为总人数
{
intyu=10;//域值
for(intk=v-1;k{
if(ADD(v-1,k)>0&&ADD(v-1,k)=BY(n)&&k!
=BY(n))//如果两个结点之间有边但交往不密切,并且分别属于两个小团体
{
cout<DFS2(k+1,n);//找下一个
}
}
if(v<=n)
DFS2(v+1,n);
}
//————————主函数————————
测试刚刚的Mgraph类中的各种成员函数是否编写正确,完成要求的功能。
voidmain()
{
cout<<"|欢迎使用社会网络分析系统|"<intn,e,m;//n总人数,e总关系数,m某个人员的数字代码
cout<<"请输入该社会网络总人数:
";
cin>>n;
char*a=newchar[n];//a是指针,a的值是新建数组的首地址,a[0],a[1]等
cout<<"请依次输入人员名称:
";
for(inti=0;i{cin>>a[i];}
cout<<"请输入该社会网络的关系总数:
";
cin>>e;
MgraphG(a,n,e);
cout<<"以下是该社会网络对应的邻接矩阵:
"<G.PrintGraph();
cout<<"******************社会网络分析中******************:
"<G.centre(n);
G.huoyue(n);
G.bianyuan(n);
cout<<"—→小团体是:
";
G.DFS(0,n);
cout<cout<<"—→联系小团体的桥接人物是:
";
G.DFS2(1,n);
cout<cout<<"请输入一个人员的数字代码(用于查找该人员的交往圈子):
";
cin>>m;
G.quanzi(m);
}
五、调试分析
(包括调试过程中遇到的问题及解决的方法、算法的时间空间复杂性分析、经验体会)
Ø问题&改进&补充:
【问题1】:
小团体和桥接人的理解与定义
小团体:
小团体就是由交往比较密切的一群人构成的,因此要设一个域值,email数据(权值)超过这个域值才能算交往密切;一个人不能单独构成一个小团体,小团体至少要2个成员组成。
桥接人:
桥接人就是联系两个小团体的中间人,也就是说一个小团体可以通过对应的桥接人和另外一个小团体取得联系,桥接人分属于两个不同的团体。
【问题2】:
参数传递问题
目的是在一个成员函数里调用另一个成员函数中的数据,一开始想到的是将代码段直接复制,但考虑到效率的问题,没有使用;然后想到了利用全局变量,但又觉得不妥;后来问了老师,老师建议我使用参数传递的方法,将需要的数据带回。
于是做了如下修改:
主函数中,增加charteam[20][20];并将G.DFS(0);改成G.DFS(0,n,team);
使DFS查找小团体的函数中,可以使用主函数中的数据n总人数;使桥接人的函数中,可以使用DFS查找小团体的函数中的二维数组:
team[20][20]
【问题3】:
递归调用中的数据存储
为了实现桥接人的查找,要将小团体储存到一个二维数组中,在递归调用中存入数组真的不是一件简单的事,初始化数组的下标就是一件很麻烦的事情,因为递归调用每一次都会调用函数本身,若在函数体里面初始化数组下标的话,每调用一次,就会归零。
解决方法:
使用参数传递,将数组下标作为两个参数,每次调用时都将其传回,这样可以保证数组下标有效完成