圖的一些簡單演算法實現
阿新 • • 發佈:2020-07-20
1、型別宣告
鄰接矩陣
#define MAXV<最大頂點個數>
#define INF 32767 //定義∞
typedef struct
{
int no; //頂點編號
InfoType info; //頂點其他資訊
}VertexType; //頂點型別
typedef struct
{
int edges[MAXV][MAXV]; //鄰接矩陣陣列
int n,e; //頂點數,邊數
VertexType vexs[MAXV]; //存放頂點資訊
}MatGraph; //鄰接矩陣型別
鄰接表
typedef struct ANode { int adjvex; //該邊的鄰接點編號 struct ANode *nextarc; //指向下一條邊的指標 int weight; //權值 }ArcNode; typedef struct Vnode { InfoType info; //頂點其他資訊 ArcNode *firstarc; //指向第一個邊結點 }VNode; //鄰接表的頭結點型別 typedef struct { VNode adjlist[MAXV]; //鄰接表的頭結點陣列 int n,e; //頂點數和邊數 }AdjGraph; //鄰接表型別
2、不帶權有向圖鄰接矩陣
void InDs1(MatGraph g) //求每個頂點的入度 { int i,j,n; printf("各頂點入度:\n"); for(j=0;j<g.n;j++) { n=0; for(i=0;i<g.n;i++) { if(g.edges[i][j]!=0) { n++; //累計入度數 } } printf("頂點%d:%d\n",j,n); } } void OutDs1(MatGraph g) //求每個頂點的出度 { int i,j,n; printf("各頂點出度:\n"); for(i=0;i<g.n;i++) { n=0; for(j=0;j<g.n;j++) { if(g.edges[i][j]!=0) { n++; //累計出度數 } } printf("頂點%d:%d\n",i,n); } } void ZeroOutDs1(MatGraph g) //求出度為0的頂點 { int i,j,n; printf("出度為0的頂點:\n"); for(i=0;i<g.n;i++) { n=0; for(j=0;j<g.n;j++) { if(g.edges[i][j]!=0) { n++; } if(n==0) { printf("2d\n",i); } } } printf("\n"); }
3、不帶權有向圖鄰接表
void InDs2(AdjGraph *G) //求每個頂點的入度 { ArcNode *p; int A[MAXV],i; //A存放各頂點的入度 for(i=0;i<G->n;i++) //A中元素初始值0 { A[i]=0; } for(i=0;i<G->n;i++) //掃描所有頭結點 { p=G->adjlist[i].firstarc; while(p!=NULL) //掃描邊結點 { A[p->adjvex]++; //表示i到p->adjvex頂點有一條邊 p=p->nextarc; } } printf("各頂點的入度:\n"); for(i=0;i<G->n;i++) { printf("頂點%d:%d\n",i,A[i]); } } void OutDs2(AdjGraph *G) //求每個頂點的出度 { int i,n; ArcNode *p; printf("各頂點出度為:\n"); for(i=0;i<G->n;i++) //掃描所有頭結點 { n=0; p=G->adjlist[i].firstarc; while(p!=NULL) //掃描邊結點 { n++; p=p->nextarc; } printf("頂點%d:%d\n",i,n); } } void ZeroOutDs2(AdjGraph *G) //出度為0的頂點數 { int i,n; ArcNode *p; printf("出度為0的頂點數:\n"); for(i=0;i<G->n;i++) //掃描所有頭結點 { n=0; p=G->adjlist[i].firtarc; while(p!=NULL) //掃描邊結點 { n++; p=p->nextarc; } if(n==0) //輸出出邊為0的頂點編號 { printf("%2d",i); } } printf("\n"); }
4、判斷是否存在經過頂點v的迴路
int visited[MAXV]; //全域性變數陣列
void Cycle(AdjGraph *G,int u,int v,int d,bool &has)
{
//呼叫初始值has置為false,d為-1
ArcNode *p;
int w;
visited[u]=1; //置已訪問的標記
d++;
p=G->adjlist[u].firstarc; //p指向頂點u的第一個鄰接點
while(p!=NULL)
{
w=p->adjvex;
if(visited[w]==0) //若頂點w未訪問,則遞迴訪問
{
Cycle(G,w,v,d,has); //從頂點w出發搜尋
}
else if(w==v&&d>1) //u到v存在一條邊且迴路長度大於1
{
has=true;
return;
}
p=p->nexterc; //找下個鄰接點
}
}
bool hasCycle(AdjGraph *G,int v) //判斷連通圖中是否有經過頂點v的迴路
{
bool has=false;
Cycle(G,v,v,-1,has); //從頂點v出發
return has;
}
5、判斷無向圖是否為一棵樹
void DFS(AdjGraph *G,int v,int &vn,int &en)
{
//深度優先遍歷圖G,並求出遍歷過的頂點數vn和邊數en
ArcNode *p;
visited[v]=1;
vn++; //遍歷過的頂點數增1
p=G->adjlist[v].firstarc;
while(p!=NULL)
{
en++; //遍歷過的邊數增1
if(visited[p->adjvex]==0)
{
DFS(G,p->adjvex,vn,en);
}
p=p->nextarc;
}
}
bool isTree(AdjGraph *G) //判斷無向圖G是否為樹
{
int vn=0,en=0,i;
for(i=0;i<G->n;i++)
{
visited[i]=0;
}
DFS(G,1,vn,en);
//遍歷頂點為 G->n 個,遍歷邊數為 2(G->n-1),則為樹
if(vn==G->n&&en==2*(G->n-1))
{
return true;
}
else
{
return false;
}
}
6、源點到其餘各點的最短路徑
void shortPath(AdjGraph *G,int i)
{
int qu[MAXV],level[MAXV];
int fornt=0,raer=0,k,lev; //lev儲存i到訪問頂點的層數
ArcNode *p;
visited[i]=1; //i已經訪問,進隊
rear++;
qu[rear]=i;
level[rear]=0;
while(front!=rear) //隊非空
{
front=(front+1)%MAXV;
//出隊
k=qu[front];
lev=level[front];
if(k!=i)
{
printf(" 頂點%d到頂點%d的最短距離是:%d\n",i,k,lev);
}
p=G->adjlist[k].firstarc; //取k的邊表頭指標
while(p!=NULL) //依次搜尋鄰接點
{
if(visited[p->adjvex==0]) //未被訪問過
{
visited[p->adjvex]=1;
rear=(rear+1)%MAXV;
qu[rear]=p->adjvex; //訪問過的鄰接點進隊
level[rear]=lev+1;
}
p=p->nextarc; //頂點i的下一個鄰接點
}
}
}
7、所有路徑及其長度
int visited[MAXV];
void findPath(AdjGraph *G,int u,int v,int path[],int d,int length)
{
//d表示 path 中頂點個數,初始為 0;length 表示路徑長度,初始為 0
int w,i;
ArcNode *p;
//頂點u加到路徑中,d增1
path[d]=u;
d++;
visited[u]=1; //置已訪問標記
if(u==v&&d>0) //找到一條路徑就輸出
{
printf(" 路徑長度:%d,路徑:",length);
for(i=0;i<d;i++)
{
printf("%2d",path[i]);
}
printf("\n");
}
p=G->adjlist[u].firstarc; //p指向頂點u的第一個鄰接點
while(p!=NULL)
{
w=p->adjvex; //w為頂點u的鄰接點
if(visited[w]==0) //w未訪問,遞迴訪問
{
findPath(G,w,v,path,d,p->weigth+length);
}
p=p->nextarc; //p指向頂點u的下一個鄰接點
}
visited[u]=0; //重置
}