//這是一個小小的關於char類型的測驗
//scanf("%c %c") 這樣的話可以輸入 A B 但是輸入完後再輸入換行會在緩衝區中 等待下一個字符 所以應該用temp存儲換行 如果沒有temp那麼輸入換行直接就是出來結果 c3就是換行
//#include<stdio.h>
//int main()
//{
// char c1,c2,c3,temp;
// scanf("%c %c",&c1,&c2);
// scanf("%c",&temp);
// scanf("%c",&c3);
// printf("%c %c %c",c1,c2,c3);
// return 0;
//}
//A B
//C
//A B C
//Process returned 0 (0x0) execution time : 14.385 s
//Press any key to continue.
//這是另一個小小的關於char類型的測驗
//同樣scanf遇到換行就輸入完畢 但%d是需要輸入空白字符才能表示輸入完畢 空格換行tab都可以 最後一個輸入後需要換行
//鍵盤輸入的會在緩衝區 但是printf輸出的換行不會
//%d%d中間輸入的空白符不會在緩衝區 但是最後一個之後的輸入會在 並且直接影響到後續輸入的%c
//如果scanf("%d%d"),再scanf("%c"),雖然說%d是需要空白符才能表示輸入完 但是這種情況下 前面兩個%d 只有第一個可以 第二個不可以輸入完後輸空白符 否則變成了%c
//#include<stdio.h>
//int main()
//{
// int ch;
// char m,n,temp;
// int i;
//
// for(i=1;i<=3;i++)
// {
// scanf("%c%c %d",&m,&n,&ch);
// scanf("%c",&temp); //存儲%d後輸入的換行
// printf("%c %c %d\n",m,n,ch);
// }
//
// return 0;
//}
//AB 3
//A B 3
//CD 2
//C D 2
//EF 5
//E F 5
//
//Process returned 0 (0x0) execution time : 20.370 s
//Press any key to continue.
#include<stdio.h>
#include<stdlib.h>
#include<limits.h> //提供INT_MAX
#include<stdarg.h> //提供va_list va_arg va_start va_end
#define OVERFLOW -2
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAX_VERTEX_NUM 20
#define INFINITY INT_MAX //無窮大
typedef int ElemType;
typedef int Status;
typedef struct QNode
{
ElemType data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
Status InitQueue(LinkQueue *Q)
{
(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));
if(!(*Q).front) exit(OVERFLOW);
(*Q).front->next=NULL;
return OK;
}
Status QueueEmpty(LinkQueue Q)
{
return Q.front==Q.rear?TRUE:FALSE;
}
Status EnQueue(LinkQueue *Q,ElemType e)
{
QueuePtr p;
p=(QueuePtr)malloc(sizeof(QNode));
if(!p) exit(OVERFLOW);
p->next=NULL;
p->data=e;
(*Q).rear->next=p;
(*Q).rear=p;
return OK;
}
Status DeQueue(LinkQueue *Q,ElemType *e)
{
QueuePtr p;
if((*Q).front==(*Q).rear)
return ERROR;
p=(*Q).front->next;
*e=p->data;
(*Q).front->next=p->next;
if((*Q).rear==p)
(*Q).rear=(*Q).front;
free(p);
return OK;
}
typedef int VRType;
typedef char VertexType;
typedef enum
{
DG,DN,UDG,UDN //DG 0 digraph 有向圖 DN 1 directed network 有向網 UDG 2 undigraph 無向圖 UDN 3 undirected network 無向網
}GraphKind; //枚舉類型名 表示創建的圖的類型
//typedef struct
//{
//
//}InfoType;
typedef struct
{
VRType adj; //頂點間的關係 vertex relationship type
//InfoType *info; //弧相關的信息 information type
}ArcCell,AdjMatrix[MAX_VERTEX_NUM+1][MAX_VERTEX_NUM+1]; //AdjMatrix 鄰接矩陣
typedef struct
{
VertexType vexs[MAX_VERTEX_NUM+1]; //頂點類型
AdjMatrix arcs;
GraphKind kind;
int vexnum,arcnum; //arc 弧
//int IncInfo; //本來打算用來處理弧的相關信息 但我不知道怎麼處理
}MGraph;
Status visited[MAX_VERTEX_NUM+1]; //標誌數組
void (*visitFunc)(VertexType e); //函數指針變量
Status CreateGraph(MGraph *G)
{
int n;
printf("0:有向圖\n");
printf("1:有向網\n");
printf("2:無向圖\n");
printf("3:無向網\n");
printf("請輸入操作的編號:\n");
scanf("%d",&n);
printf("\n");
(*G).kind=(GraphKind)n; //不要遺漏這個地方 //不能把整數直接賦值給枚舉類型變量(要對整數進行強制轉換)
switch(n)
{
case 0:
return CreateDG(G);
break;
case 1:
return CreateDN(G);
break;
case 2:
return CreateUDG(G);
break;
case 3:
return CreateUDN(G);
break;
}
}
int LocateVex(MGraph G,VertexType v)
{
int i;
for(i=1;i<=G.vexnum;i++)
{
if(v==G.vexs[i])
return i;
}
return ERROR;
}
Status CreateDG(MGraph *G)
{
int i,j,k;
char temp; //如果涉及字符輸入的話 換行會在緩衝區 最後被當作字符錄入
VertexType v1,v2;
printf("請依次輸入頂點數,弧數:\n");
scanf("%d%d",&(*G).vexnum,&(*G).arcnum);
//存取換行
scanf("%c",&temp);
//先處理頂點
printf("請依次輸入頂點:\n");
for(i=1;i<=(*G).vexnum;i++)
scanf("%c",&(*G).vexs[i]); //第一次這裏%c後面有一個空格 出現了問題
//存取換行
scanf("%c",&temp);
//初始化鄰接矩陣
for(i=1;i<=(*G).vexnum;i++)
{
for(j=1;j<=(*G).vexnum;j++)
{
(*G).arcs[i][j].adj=0;
}
}
//再處理弧
printf("請輸入弧:\n");
for(k=1;k<=(*G).arcnum;k++)
{
scanf("%c%c",&v1,&v2);
scanf("%c",&temp);
i=LocateVex(*G,v1);
j=LocateVex(*G,v2);
if(!i||!j)
return ERROR;
(*G).arcs[i][j].adj=1;
}
return OK;
}
Status CreateDN(MGraph *G)
{
int i,j,k;
VertexType v1,v2;
char temp;
VRType w;
printf("請依次輸入頂點數,弧數:\n");
scanf("%d%d",&(*G).vexnum,&(*G).arcnum);
scanf("%c",&temp);
printf("請依次輸入頂點:\n");
for(i=1;i<=(*G).vexnum;i++)
scanf("%c",&(*G).vexs[i]);
scanf("%c",&temp);
for(i=1;i<=(*G).vexnum;i++)
{
for(j=1;j<=(*G).vexnum;j++)
{
(*G).arcs[i][j].adj=INFINITY;
}
}
printf("請輸入弧及相應的權值:\n");
for(k=1;k<=(*G).arcnum;k++)
{
scanf("%c%c %d",&v1,&v2,&w);
scanf("%c",&temp); //存取%d後面的換行
i=LocateVex(*G,v1);
j=LocateVex(*G,v2);
if(!i||!j)
return ERROR;
(*G).arcs[i][j].adj=w;
}
return OK;
}
Status CreateUDG(MGraph *G)
{
int i,j,k;
char temp; //如果涉及字符輸入的話 換行會在緩衝區 最後被當作字符錄入
VertexType v1,v2;
printf("請依次輸入頂點數,弧數:\n");
scanf("%d%d",&(*G).vexnum,&(*G).arcnum);
//存取換行
scanf("%c",&temp);
//先處理頂點
printf("請依次輸入頂點:\n");
for(i=1;i<=(*G).vexnum;i++)
scanf("%c",&(*G).vexs[i]);
//存取換行
scanf("%c",&temp);
//初始化鄰接矩陣
for(i=1;i<=(*G).vexnum;i++)
{
for(j=1;j<=(*G).vexnum;j++)
{
(*G).arcs[i][j].adj=0;
}
}
//再處理弧
printf("請輸入弧:\n");
for(k=1;k<=(*G).arcnum;k++)
{
scanf("%c%c",&v1,&v2);
scanf("%c",&temp);
i=LocateVex(*G,v1);
j=LocateVex(*G,v2);
if(!i||!j)
return ERROR;
(*G).arcs[i][j].adj=1;
(*G).arcs[j][i].adj=1;
}
return OK;
}
Status CreateUDN(MGraph *G)
{
int i,j,k;
VertexType v1,v2;
char temp;
VRType w;
printf("請依次輸入頂點數,弧數:\n");
scanf("%d%d",&(*G).vexnum,&(*G).arcnum);
scanf("%c",&temp);
printf("請依次輸入頂點:\n");
for(i=1;i<=(*G).vexnum;i++)
scanf("%c",&(*G).vexs[i]);
scanf("%c",&temp);
for(i=1;i<=(*G).vexnum;i++)
{
for(j=1;j<=(*G).vexnum;j++)
{
(*G).arcs[i][j].adj=INFINITY;
}
}
printf("請輸入弧及相應的權值:\n");
for(k=1;k<=(*G).arcnum;k++)
{
scanf("%c%c %d",&v1,&v2,&w);
scanf("%c",&temp); //存取%d後面的換行
i=LocateVex(*G,v1);
j=LocateVex(*G,v2);
if(!i||!j)
return ERROR;
(*G).arcs[i][j].adj=w;
(*G).arcs[j][i].adj=w;
}
return OK;
}
void ClearGraph(MGraph *G)
{
(*G).vexnum=0;
(*G).arcnum=0;
//(*G).IncInfo=0;
}
VertexType GetVex(MGraph G,int order) //這裏需要注意給的是頂點下標 不是直接給的頂點
{
if(order>=1&&order<=G.vexnum)
return G.vexs[order];
else return '\0';
}
Status PutVex(MGraph *G,VertexType v,VertexType value) //這裏需要注意給的直接是頂點
{
int i;
i=LocateVex(*G,v);
if(!i) return ERROR;
else
{
(*G).vexs[i]=value;
return OK;
}
}
int FirstAdjVex(MGraph G,VertexType v)
{
int i,j,t;
i=LocateVex(G,v);
if(i)
{
if(G.kind%2) //網
t=INFINITY;
else t=0; //圖
for(j=1;j<=G.vexnum;j++)
{
if(G.arcs[i][j].adj!=t)
return j;
}
}
return 0;
}
int NextAdjVex(MGraph G,VertexType v,VertexType w)
{
int i,j,k,t;
i=LocateVex(G,v);
j=LocateVex(G,w);
if(i&&j)
{
if(G.kind%2)
t=INFINITY;
else t=0;
for(k=j+1;k<=G.vexnum;k++)
{
if(G.arcs[i][k].adj!=t)
return k;
}
}
return 0;
}
Status InsertVex(MGraph *G,VertexType v)
{
if((*G).vexnum==MAX_VERTEX_NUM)
return ERROR;
int i,j,t;
i=(*G).vexnum+1;
(*G).vexs[i]=v;
if((*G).kind%2)
t=INFINITY;
else t=0;
for(j=1;j<=i;j++) //這個地方不是j<=(*G).vexnum而是j<=k 因爲增加了頂點 個數增加了 只是這步操作之前原來的頂點個數還需要用到 所以暫時沒有加一 若是原來的 那麼新增的會是亂值
{
(*G).arcs[i][j].adj=t;
(*G).arcs[j][i].adj=t;
}
(*G).vexnum++;
return OK;
}
Status DeleteVex(MGraph *G,VertexType v) //注意內部處理順序
{
int i,j,k,t;
i=LocateVex(*G,v);
if(!i) return ERROR;
if((*G).kind%2)
t=INFINITY;
else t=0;
//處理弧數
for(j=1;j<=(*G).vexnum;j++)
{
if((*G).arcs[i][j].adj!=t)
(*G).arcnum--;
if((*G).kind%2)
{
if((*G).arcs[j][i].adj!=t)
(*G).arcnum--;
}
}
//處理列
for(j=1;j<=(*G).vexnum;j++)
{
for(k=i+1;k<=(*G).vexnum;k++)
{
(*G).arcs[j][k-1].adj=(*G).arcs[j][k].adj;
}
}
//處理行
for(j=i+1;j<=(*G).vexnum;j++) //j表示行 k表示列
{
for(k=1;k<(*G).vexnum;k++) //這裏需要注意因爲上述列已經往前覆蓋 所以這裏k不等於(*G).vexnum了
{
(*G).arcs[j-1][k]=(*G).arcs[j][k];
}
}
//處理頂點
for(j=i;j<(*G).vexnum;j++)
(*G).vexs[j]=(*G).vexs[j+1];
(*G).vexnum--;
return OK;
}
Status InsertArc(MGraph *G,VertexType v,VertexType w,VRType adj)
{
int i,j;
i=LocateVex(*G,v);
j=LocateVex(*G,w);
if(!i||!j)
return ERROR;
(*G).arcs[i][j].adj=adj;
if(!(*G).kind%2)
(*G).arcs[j][i].adj=adj;
(*G).arcnum++;
return OK;
}
Status DeleteArc(MGraph *G,VertexType v,VertexType w)
{
int i,j,t;
i=LocateVex(*G,v);
j=LocateVex(*G,w);
if(!i||!j)
return ERROR;
if((*G).kind%2)
t=INFINITY;
else t=0;
(*G).arcs[i][j].adj=t;
if((*G).kind%2)
(*G).arcs[j][i].adj=t;
(*G).arcnum--;
return OK;
}
void DFSTraverse(MGraph G,void(visit)(VertexType e))
{
int v;
//VisitFunc是全局變量 所以在調用的時候DFS就不用設置參數了
visitFunc=visit; //VisitFunc是函數指針 visit是函數名 函數指針的用法是 直接將函數名賦值給函數指針 函數指針在調用的時候 和函數名是一樣的
for(v=1;v<=G.vexnum;v++)
visited[v]=FALSE;
for(v=1;v<=G.vexnum;v++)
{
if(!visited[v])
DFS(G,v);
}
}
void DFS(MGraph G,int v)
{
int w;
visited[v]=TRUE;
visitFunc(G.vexs[v]);
for(w=FirstAdjVex(G,G.vexs[v]);w;w=NextAdjVex(G,G.vexs[v],G.vexs[w]))
{
if(!visited[w])
DFS(G,w);
}
}
void BFSTraverse(MGraph G,void(visit)(VertexType e))
{
int v,w;
ElemType e;
for(v=1;v<=G.vexnum;v++)
visited[v]=FALSE;
LinkQueue Q;
InitQueue(&Q);
for(v=1;v<=G.vexnum;v++)
{
if(!visited[v])
{
visited[v]=TRUE;
visit(G.vexs[v]);
EnQueue(&Q,v);
while(!QueueEmpty(Q))
{
DeQueue(&Q,&e);
for(w=FirstAdjVex(G,G.vexs[e]);w;w=NextAdjVex(G,G.vexs[e],G.vexs[w]))
{
if(!visited[w])
{
visited[w]=TRUE;
visit(G.vexs[w]);
EnQueue(&Q,w);
}
}
}
}
}
}
void visit(VertexType e)
{
printf("%c ",e);
}
void PrintGraph(MGraph G)
{
int i,j;
if(!G.vexnum&&!G.arcnum)
printf("這是空(圖)表!\n");
else
{
printf(" ");
for(i=1;i<=G.vexnum;i++)
printf("%2c ",G.vexs[i]);
printf("\n");
for(i=1;i<=G.vexnum;i++)
{
printf("%c ",G.vexs[i]);
for(j=1;j<=G.vexnum;j++)
{
if(G.arcs[i][j].adj==INFINITY)
printf("∞ "); //電腦中輸出無窮大的方法 ctrl+shif+B->數學->尋找無窮大
else printf("%2d ",G.arcs[i][j]);
}
printf("\n");
}
}
}
int main()
{
MGraph G;
VertexType v;
CreateGraph(&G);
PrintGraph(G);
printf("\n");
printf("深度遍歷結果是:\n");
DFSTraverse(G,visit);
printf("\n");
printf("廣度遍歷結果是:\n");
BFSTraverse(G,visit);
printf("\n");
v=GetVex(G,2);
printf("%c\n",v);
printf("\n");
PutVex(&G,v,'H');
InsertVex(&G,'I');
DeleteVex(&G,'H');
InsertArc(&G,'I','D',2);
DeleteArc(&G,'D','C');
PrintGraph(G);
printf("\n");
printf("深度遍歷結果是:\n");
DFSTraverse(G,visit);
printf("\n");
printf("廣度遍歷結果是:\n");
BFSTraverse(G,visit);
printf("\n");
return 0;
}
測試結果:
0:有向圖
1:有向網
2:無向圖
3:無向網
請輸入操作的編號:
1
請依次輸入頂點數,弧數:
6 10
請依次輸入頂點:
ABCDEF
請輸入弧及相應的權值:
AB 5
AD 7
BC 4
CA 8
CF 9
DC 5
DF 6
ED 5
FA 3
FE 1
A B C D E F
A ∞ 5 ∞ 7 ∞ ∞
B ∞ ∞ 4 ∞ ∞ ∞
C 8 ∞ ∞ ∞ ∞ 9
D ∞ ∞ 5 ∞ ∞ 6
E ∞ ∞ ∞ 5 ∞ ∞
F 3 ∞ ∞ ∞ 1 ∞
深度遍歷結果是:
A B C F E D
廣度遍歷結果是:
A B D C F E
B
A C D E F I
A ∞ ∞ 7 ∞ ∞ ∞
C 8 ∞ ∞ ∞ 9 ∞
D ∞ ∞ ∞ ∞ 6 ∞
E ∞ ∞ 5 ∞ ∞ ∞
F 3 ∞ ∞ 1 ∞ ∞
I ∞ ∞ 2 ∞ ∞ ∞
深度遍歷結果是:
A D F E C I
廣度遍歷結果是:
A D F E C I
Process returned 0 (0x0) execution time : 66.828 s
Press any key to continue.
Data Structure --- MGraph
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.