數據結構:圖(建立及遍歷)

圖的創建

圖的鄰接矩陣存儲

#define INFINITY 65535
/*鄰接矩陣表示圖*/
/*圖結點的定義*/ 
typedef int WeightType; //抽象一下,WeightType可取各種類型,DataType什麼也是一樣的 
typedef struct GNode *PtrToNode;
struct GNode{
int Nv;//頂點數 
int Ne;//邊數
WeightType G[maxVertexNum][MaxVertexNum]; //鄰接矩陣,裏面放權重Weight 
DataType Data[maxVertexNum];//存頂點的數據 不是必須有 
};
typedef PtrToNode MGraph;

/*初始化,無邊*/
typedef int Vertex;
MGraph craeatGraph(int VertexNum) //返回一個圖嗷!!! 
{
	MGraph Graph;
	Vertex v,w;
	Graph=(MGraph)malloc(sizeof(struct GNode));
	Graph->Nv=VertexNum;
	Graph->Ne=0;//還沒有邊
	
	for(v=0;v<Graph->Nv;v++)
	{
		for(w=0;w<Graph->Nv;w++)
		{
			Graph->G[v][w]=INFINITY;//define INFINITY 65535(無限大) 
		}
	}
	
	return Graph;
}

/*插入邊*/ 
typedef struct ENode *PtrToNode;//先定義一個邊結構 
struct ENode{
	Vertex v1,v2;//有向邊 <v1,v2> 
	WeightType weight;//權重 
};
typedef PtrToNode Edge;


void insertEdge(MGraph Graph,Edge E)
{
	Graph->G[E->v1][E->v2]=E->weight;
	/*如果是有向圖*/
	Graph->G[E->v2][E->v1]=E->weight;
}

void BuildGraph0()
{
	//此處待補充
}


/*完整建圖*/
/*輸入格式
Nv Ne
V1 V2 Weight   */ 
/*不用上面的鋪墊(工程性比較強....)的建圖*/
int G[maxv][maxv];
int Nv,Ne; 

void BuildGraph()
{
	int i,j,Nv,Ne,v1,v2,weight;
	
	scanf("%d",&Nv);
	for(i=0;i<Nv;i++)
	{
		for(j=0;j<Nv;j++)
			G[i][j]=0;
	}
	scanf("%d",&Ne);
	for(i=0;i<Ne;i++)
	{
		scanf("%d%d%d",&v1,&v2,&weight);
		G[v1][v2]=weight;
		G[v2][v1]=weight;
	}
}

圖的鄰接表存儲

有點吐血

//鄰接表實現  G[N]爲指針數組,對應矩陣每行一個鏈表,只存非0元素

typedef struct GNode *PtrToNode;
struct GNode{
	int Nv;//頂點數
	int Ne;//邊數
	AdjList G;//鄰接表,數組 
	 
}; 
typedef PtrToNode LGraph;
 
 
//表!
typedef struct Vnode{
	PtrToNodeVNode FirstEdge;//總是指向鏈表的第一條邊
	//DataType data;有結點的數據 

}AdjList[MaxVertexNum];


typedef struct AdjVNode *PtrToNodeVNode;//鏈表 
struct AdjVNode{
	Vertex AdjV;//鄰接點下標 
	WeightType Weight;//邊權重
	PtrToAdjVNode next;//指針域 
};

typedef int Vertex;
LGraph CreatGraph(int Vertexnum)
{
	Vertex v,w;
	LGraph Graph;
	Graph=(LGraph)malloc(sizeof(struct GNode));
	Graph->Nv=Vertexnum;
	Graph->Ne=0;
	
	for(v=0;v<Vertexnum;v++)
	{
		Graph->G[v].FirstEdge=NULL;
	}
	return Graph;
 } 

struct node2{
	Vertex v1,v2;
	int weight;
};
typedef struct node2 Edge;

void insert(LGraph Graph,Edge E)
{
	PtrToAdjVNode newNode;//先建立鄰接點 
	Newnode=(PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
	Newnode->AdjV=E->v2;	
	Newnode->Weight=E->weight;
	//將v2插入v1表頭
	Newnode->next=Graph->G[E->v1].FirstEdge; 
	Graph->G[E->v1].FirstEdge=Newnode; 
	
	//如果是無向圖
		PtrToAdjVNode newNode;//先建立鄰接點 
	Newnode=(PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
	Newnode->AdjV=E->v1;	
	Newnode->Weight=E->weight;
	//將v1插入v2表頭
	Newnode->next=Graph->G[E->v2].FirstEdge;
	Graph->G[E->v2].FirstEdge=Newnode;   
} 

最終…

void BuildGraph(){
	int i;
	int v1,v2,w;
	AdjList NewNode;
	scanf("%d",&Nv);
	for(i=0;i<Nv;i++){
		Graph[i] = (AdjList)malloc(sizeof(struct AdjVNode));
		Graph[i]->adjv = i;
		Graph[i]->next = NULL;
	}
	scanf("%d",&Ne);
	for(i=0;i<Ne;i++){
		scanf("%d %d %d",&v1,&v2,&w);
		NewNode = (AdjList)malloc(sizeof(struct AdjVNode));
		NewNode->adjv = v1;
		NewNode->weight = w;
		
		NewNode->next = Graph[v2]->next;
		Graph[v2]->next = NewNode;
		
		NewNode = (AdjList)malloc(sizeof(struct AdjVNode));
		NewNode->adjv = v2;
		NewNode->weight = w;
		
		NewNode->next = Graph[v1]->next;
		Graph[v1]->next = NewNode;
	}
} 


void print(){
	AdjList tmp;
	int i;
	for(i=0;i<Nv;i++){
		tmp = Graph[i];
		while(tmp){
			printf("%d ",tmp->adjv);
			tmp = tmp->next;
		}
		printf("\n");
	}
}

簡化!!!比前面的簡單太多

注意此處的圖是一個結點類型(指向結構體)的指針數組,下標代表序號

#include<stdio.h>
#include<stdlib.h>
#define MaxVertexNum 100
typedef struct AdjVNode *AdjList;
struct AdjVNode{
	int weight;  // 權值 
  	int adjv;   // 下標 
	AdjList next;  // 其後一個 
};
AdjList Graph[MaxVertexNum];
int Ne,Nv;

// 建圖
void BuildGraph(){
	int i;
	int v1,v2,w;
	AdjList NewNode;
	scanf("%d",&Nv);
	for(i=0;i<Nv;i++){
		Graph[i] = (AdjList)malloc(sizeof(struct AdjVNode));
		Graph[i]->adjv = i;
		Graph[i]->next = NULL;
	}
	scanf("%d",&Ne);
	for(i=0;i<Ne;i++){
		scanf("%d %d %d",&v1,&v2,&w);
		NewNode = (AdjList)malloc(sizeof(struct AdjVNode));
		NewNode->adjv = v1;
		NewNode->weight = w;
		
		NewNode->next = Graph[v2]->next;
		Graph[v2]->next = NewNode;
		//-------分割線------------
		NewNode = (AdjList)malloc(sizeof(struct AdjVNode));
		NewNode->adjv = v2;
		NewNode->weight = w;
		
		NewNode->next = Graph[v1]->next;
		Graph[v1]->next = NewNode;
	}
} 

void print(){
	AdjList tmp;
	int i;
	for(i=0;i<Nv;i++){
		tmp = Graph[i];
		while(tmp){
			printf("%d ",tmp->adjv);
			tmp = tmp->next;
		}
		printf("\n");
	}
}

int main(){
	
	BuildGraph();
	print();
	return 0;
}

圖的遍歷

DFS

爲了好理解,先用僞代碼來表示一下

void DFS(Vertex v)
{
	visited[v]=true;
	for(v的每個鄰接點w)
	{
		if(!visited[w])
			DFS(w);
	}
}

BFS

類似於樹的層序遍歷,需要新建一個隊列

void BFS(Vertex v)
{
	queue<Vertex> q;
	visited[v]=true;
	q.push(v);
	while(!q.empty())
	{
		v=q.front();q.pop();
		for(v的每個鄰接點w)
		{
			if(!visited[w])
			{
				visited[w]=true;
				q.push(w);
			}
		}
	}
}


void BFS(int i)
{
	queue<int> q;
	int temp;
	bool visited[MaxVertexNum];
	AdjList p;
	printf("%d",i);
	q.push(i);
	while(!q.empty())
	{
		temp=q.front();
		q.pop();
		for(p=Graph[temp];p!=NULL;p=p->next)
		{
			if(!visited[p->adjv])
			{
				visited[p->adjv]=true;
				printf("%d ",p->adjv);
				q.push(p->adjv);
			}
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章