六度空間(廣度優先遍歷 · 數據結構 · 圖)

原理就看書吧,看書吧,六度空間的解讀好麻煩啊, 陳越姥姥的講解賽高了。

六度空間理論又稱作六度分隔(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++


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章