六度空间(广度优先遍历 · 数据结构 · 图)

原理就看书吧,看书吧,六度空间的解读好麻烦啊, 陈越姥姥的讲解赛高了。

六度空间理论又称作六度分隔(Six Degrees of Separation理论。这个理论可以通俗地阐述为:你和任何一个陌生人之间所间隔的人不会超过六个,也就是说,最多通过五个人你就能够认识任何一个陌生人。如图1所示。

                           《六度空间(广度优先遍历 · 数据结构 · 图)》

1 六度空间示意图

六度空间理论虽然得到广泛的认同,并且正在得到越来越多的应用。但是数十年来,试图验证这个理论始终是许多社会学家努力追求的目标。然而由于历史的原因,这样的研究具有太大的局限性和困难。随着当代人的联络主要依赖于电话、短信、微信以及因特网上即时通信等工具,能够体现社交网络关系的一手数据已经逐渐使得六度空间理论的验证成为可能。

假如给你一个社交网络图,请你对每个节点计算符合六度空间理论的结点占结点总数的百分比。

输入格式:

输入第1行给出两个正整数,分别表示社交网络图的结点数N1<N≤10​4​​,表示人数)、边数M≤33×N,表示社交关系数)。随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个结点的编号(节点从1N编号)。

输出格式:

对每个结点输出与该结点距离不超过6的结点数占结点总数的百分比,精确到小数点后2位。每个结节点输出一行,格式为结点编号:(空格)百分比%”

输入样例:

10 9
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9

9 10

输出样例:

1:  70.00%
2:  80.00%
3:  90.00%
4:  100.00%
5:  100.00%
6:  100.00%
7:  100.00%
8:  90.00%
9:  80.00%
10: 70.00%

代码如下:

#include<stdio.h>  
#include<stdlib.h>  
#define ERROR -1   //标记错误,表示生成树不存在
#define MAXSIZE 100 
#define MaxVertexNum 100 
#define SIX 6 

int Visited[MaxVertexNum];
typedef int Vertex; 
typedef int WeightType; 
typedef char DataType; 

typedef struct ENode *PtrToENode; 
struct ENode{ 
	Vertex V1, V2; //有向边  
	WeightType Weight; //权重  
}; 
typedef PtrToENode Edge; 

typedef struct AdjVNode *PtrToAdjVNode; 
struct AdjVNode{  
	Vertex Adjv; //邻接点下标 
	WeightType Weight; //边权重 
	PtrToAdjVNode Next;  
}; 

typedef struct Vnode{  //顶点表头节点的定义 
	PtrToAdjVNode FirstEdge; //边表头指针 
	DataType Data; //存顶针的数据 
	//注意:很多情况下,顶点无数据,此时Data可以不用出现 
}AdjList[MaxVertexNum ]; //AdjList是邻接表类型 

typedef struct GNode *PtrToGNode; 
struct GNode{ 
	int Nv;//顶点数  
	int Ne;//边数 
	AdjList G;//邻接表 
}; 
typedef PtrToGNode LGraph; 

typedef int Position;
typedef struct QNode *PtrToQNode;
struct QNode{
	int *Date;
	Position Front, Rear;
	int MAXSize;
};
typedef PtrToQNode Queue; 

Queue CreateQueue(int MAXSize)  
{  
    Queue Q = (Queue)malloc(sizeof(struct QNode)); 
	Q->Date = (int*)malloc(MAXSize*sizeof(int)); 
	Q->Front = Q->Rear = 0;
	Q->MAXSize = MAXSize;
	return Q;
}  

bool isFull(Queue Q) 
{ 
	return ((Q->Rear+1)%Q->MAXSize==Q->Front);
} 

bool IsEmpty(Queue Q)  
{ 
	return (Q->Front==Q->Rear); 
} 

int DeleteQ(Queue Q)  
{ 
   if(IsEmpty(Q)) 
   { 
   	printf("队列空");
   	return ERROR;
   }else{ 
   	Q->Front = (Q->Front+1)%Q->MAXSize;
   	//printf("Front = %d ", Q->Front);
   	//printf("delete = %d\n",Q->Date[Q->Front]);
   	return Q->Date[Q->Front];
   }  
} 

bool AddQ(Queue Q, int X)  
{ 
	if(isFull(Q)) 
	{ 
		printf("队列满");
		return false;
	} 
	else
	{ 
		Q->Rear = (Q->Rear+1)%Q->MAXSize;
		Q->Date[Q->Rear] = X;
	//	printf("Rear = %d ", Q->Rear);
	//	printf("add = %d \n", Q->Date[Q->Rear]);
		return true;
	} 
} 


LGraph CreateGraph(int VertexNum)   
{  
	 Vertex V;  
	//初始化一个 VertexNum 个顶点但没有边的图 
	 LGraph Graph;  
	 Graph = (LGraph)malloc(sizeof(struct GNode));  
	 Graph->Nv = VertexNum; 
	 Graph->Ne = 1;//初始化邻接表头指针 
	 
	 for(V=1; V<Graph->Nv; V++)   
	 Graph->G[V].FirstEdge = NULL;  
	      
	 return Graph;  
}  
 
void InitializeVisited(int Nv) 
{ 
     Vertex V; 
	 for( V=1; V<=Nv; V++ ) 
	 { 
	 Visited[V] = false; 
	// printf("**** = %d \n", V); 
	 } 
} 

//Visited[]为全局变量,已经初始化为false
int SDS_BFS(LGraph Graph, Vertex S) //广度优先  
{ 
	Queue Q; 
	Vertex V, Last, Tail;
	PtrToAdjVNode W;
	int Count, Level; 
	 
	Q = CreateQueue(MAXSIZE);//创建空列队,MAXSIZE为外部定义的常数 
	//访问顶点S:此处可根据具体访问需要改写 
	//Visit(S); 
	Visited[S] = true;
	Count = 1;
	Level = 0;
	Last = S;
	AddQ(Q, S);//S入队 第一次只有头结点入队 
	
    while(!IsEmpty(Q)) 
	{
		V = DeleteQ(Q);//弹出结点 
	//	printf(" [%d] ", V);
		for(W=Graph->G[V].FirstEdge; W; W = W->Next){ //对图中的每个顶点W 
		//若W是V的邻接点且并未访问过 
	    if(!Visited[W->Adjv])//若为被访问过 
	    //Visit(W); 
	    { 
	    Visited[W->Adjv] = true; 
		Count++; 
		Tail=W->Adjv;//当前层尾 
	    AddQ(Q, W->Adjv);//W->Adjv入队 
		} 
	} 
	if( V==Last ){
		Level++;
	//printf("%d ", Level);
		Last = Tail;
	}
	if(Level==SIX) break; 
	}   
        //DestoryQueue(Q); 
	return Count; 
}  

void SIX_Degrees_of_Separation( LGraph Graph )   
{ 
   	Vertex V;
   	int Count = 0;
   	
   	for(V=1; V<=Graph->Nv; V++)
   	{
   		InitializeVisited(Graph->Nv);
   		Count = SDS_BFS(Graph, V);
   		//printf("\n");
   		//printf("count = %d ", Count);
   		printf("%d:", V);
   		if( V<10 )
   		printf("  ");
   		else
   		printf(" ");
   		printf("%.2f%%\n", 100.0*(double)Count/(double)Graph->Nv);
   	}
} 

void InsertEdge(LGraph Graph, Edge E)  
{ 
	PtrToAdjVNode NewNode; 
	//插入边<V1, V2>
	//为V2建立新的邻接点                                                    
	NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));                   
	NewNode->Adjv =E->V2;  
	//将V2插入V1的表头           
	NewNode->Next = Graph->G[E->V1].FirstEdge;      
	Graph->G[E->V1].FirstEdge = NewNode;                                                               
	//若是-无向图-还需议案插入<V2, V1>
	// 为V1建立新的邻接点 
	NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode)); 
	NewNode->Adjv = E->V1; 
	//将V1插入V2的表头 
	NewNode->Next = Graph->G[E->V2].FirstEdge; 
	Graph->G[E->V2].FirstEdge = NewNode; 
} 

LGraph BuildGraph()  
{ 
	LGraph Graph; 
	Edge E; 
	Vertex V; 
	int Nv, i; 
	
	scanf("%d", &Nv); //读入顶点个数 
	Graph = CreateGraph(Nv); 
	scanf("%d", &(Graph->Ne)); //读入边数 
	if( Graph->Ne!=0 ) 
	E = (Edge)malloc(sizeof(struct ENode));//建立边结点  
	//读入边,格式为“起点,终点, 权重”,插入邻接矩阵  
	for( i=0; i<Graph->Ne; i++) 
	{                                                                                             
		scanf("%d %d", &E->V1, &E->V2); 
		InsertEdge(Graph, E); 
	}  
	
	return Graph; 
}  

int main()
{
	LGraph Graph = BuildGraph();
	SIX_Degrees_of_Separation(Graph);
	return 0;
}

《六度空间(广度优先遍历 · 数据结构 · 图)》

编译器:DEV C++

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/Mas1461261388/article/details/80528604
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞