建立一個圖,並且遍歷---MOOC浙大資料結構
阿新 • • 發佈:2019-01-24
建圖
以鄰接表方式儲存的圖型別
typedef struct GNode *PtrToGNode; struct GNode{//整個圖 int Nv;//頂點數 int Ne;//邊數、 AdjList G;//鄰接表 }; typedef PtrToGNode LGraph; typedef struct AdjVNode *PtrToAdjVNode; typedef struct Vnode{//頂點 PtrToAdjuVNode FirstEdge; DataType Data;/*存頂點的資料*/ }AdjList[MaxVertexNum];//鄰接表型別 typedef struct AdjVNode *PtrToAdjVNode; struct AdjVNode{//鄰接點 Vertex AdjV;//鄰接點下標 WeightType Weight;//邊權重 PtrToAdjVNode Next; }; typedef struct ENode *PtrToENode; struct ENode{ Vertex V1, V2; //有向邊《V1,V2》 WeightType Weight; //權重(如果需要) }; typedef PtrToENode Edge;
Vertex V1, V2; //有向邊《V1,V2》 WeightType Weight; //權重(如果需要) }; typedef PtrToENode Edge;
LGraph初始化
typedef int Vertex;//用頂點下標表示頂點,為整型int LGraph CreateGraph(int VertexNum) { Vertex V, W; LGraph Graph; Graph = (LGraph)malloc(sizeof(struct GNode)); Graph->Nv = VertexNum; Graph->Ne = 0; /*預設頂點編號從0開始,到Graph->Nv-1 */ for (V = 0; V < Graph->Nv; V++) Graph->G[V].FirstEdge = NULL; return Graph; }
向LGraph中插入邊
void InsertEdge(LGraph Graph, Edge E) { PtrToAdjVNode NewNode; /*插入邊《V1,V2》*/ NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));//V2建立鄰接點 NewNode->AdjV = E->V2; NewNode->Weight = E->Weight; /*將V2插入V1的表頭*/ NewNode->Next = Graph->G[E->V1].FirstEdge; Graph->G[E->V1].FirstEdge = NewNode; /*如果是無向圖,還要插入邊《V2,V1》*/ /*插入邊《V2,V1》*/ NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));//V1建立鄰接點 NewNode->AdjV = E->V1; NewNode->Weight = E->Weight; /*將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 %d",&E->V1, &E->V2, &E->Weight);
InsertEdge(Graph, E);
}
}
/*如果頂點有資料,甚至是結構體,那麼還要讀入資料*/
for (V = 0; V < Graph->Nv; V++)
scanf("%c", &(Graph->Data[V]));
return Graph;
}
考試寫法:
struct graph{
int node;
graph* p_next;
graph(int x):node(x),p_next(NULL){}
};
graph* p=new graph(0);//圖的頭,連結串列頭
graph* tmp=p;
While()//迴圈條件
{
tmp->node=a;//節點的值
tmp->p_next=new graph(b);//邊的值
tmp=tmp->p_next;
}
#include <iostream>
#include <vector>
#include <string>
#include <string.h>
#include <algorithm>
using namespace std;
struct graph{
int node;
graph* p_next;
graph(int x) :node(x), p_next(NULL){}
};
int N;
void DFS(int vertex,vector<int>& vec,int value,graph** head,int * visit)
{
value++;
visit[vertex] = 1;
int flag = false;
graph* tmp = head[vertex];
while (tmp->p_next != NULL)
{
tmp = tmp->p_next;
if (!visit[tmp->node])
{
flag = true;
DFS(tmp->node,vec,value,head,visit);
}
}
if (!flag)
{
vec.push_back(value-1);
}
}
int main()
{
cin >> N;
int *visit = new int[N + 1];
for (int i = 0; i < N + 1; i++)
{
visit[i] = 0;
}
graph** head = new graph*[N];
for (int i = 1; i <= N;i++)
{
head[i] = new graph(i);
}
int saveN = N - 1;
while (saveN--)
{
int tmp1, tmp2;
cin >> tmp1>>tmp2;
graph* tmp = head[tmp1];
while (tmp->p_next != NULL)
{
tmp = tmp->p_next;
}
tmp->p_next = new graph(tmp2);
}
vector<int> vec;
DFS(1, vec, 0, head, visit);
sort(vec.begin(),vec.end());
int res = 0;
for (int i = 0; i < vec.size()-1;i++)
{
res += 2 * vec[i];
}
res += vec[vec.size() - 1];
cout << res<<endl;
return 0;
}
矩陣方式:
定義圖:
typedef struct GNode *PtrToGNode;
struct GNode{
int Nv;//頂點數
int Ne;//邊數、
/*有可能有權值int value*/
WeightType G[MaxVertexNum][MaxVertexNum];
DataType Data[MaxVertexNum];//存頂點的資料型別
};
typedef PtrToGNode MGraph;//以鄰接矩陣儲存的圖型別
建立圖:
typedef int Vertex;//用頂點下標表示頂點,為整型int
MGraph CreateGraph(int VertexNum)
{
Vertex V, W;
MGraph Graph;
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] = 0;//有權圖用INFINITY無窮大表示沒有邊
return Graph;
}
插入邊:
typedef struct ENode *PtrToENode;
struct ENode{
Vertex V1, V2; //有向邊《V1,V2》
WeightType Weight; //權重(如果需要)
};
typedef PtrToENode Edge;
void InsertEdge(MGraph Graph, Edge E)
{
Graph->G[E->V1][E->V2] = E->Weight;//V1,V2邊
Graph->G[E->V2][E->V1] = E->Weight;//無向圖V2,V1
}
完整建立一個MGraph
MGraph BuildGraph()
{
MGraph 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 %d",&E->V1, &E->V2, &E->Weight);
InsertEdge(Graph, E);
}
}
/*如果頂點有資料,甚至是結構體,那麼還要讀入資料*/
for (V = 0; V < Graph->Nv; V++)
scanf("%c", % (Graph->Data[V]));
return Graph;
}
考試寫法:
上述兩種標準寫法,封裝好了底層的介面,讓呼叫者無須關注底層的實現,到底是用矩陣?還是用連結串列?
遍歷
深度優先
void DFS ( Vertex V )
{ visited[ V ] = true;
for ( V 的每個鄰接點W )
if ( !visited[ W ] )
DFS( W );
}
廣度優先
void BFS ( Vertex V )
{
visited[V] = true;
Enqueue(V, Q);
while(!IsEmpty(Q)){
V = Dequeue(Q);
for ( V 的每個鄰接點W )
if ( !visited[W] ) {
visited[W] = true;
Enqueue(W, Q);
}
}
}
DFS的例子:
BFS的例子: