參考資料
http://blog.csdn.net/andyelvis/article/details/1728378
圖的相關概念##
待補充
用鄰接矩陣創建圖無向圖##
#define TRUE 1
#define FALSE 0
#define MAX_LENGTH 100
typedef int Boolean;
Boolean visited[MAX_LENGTH]; // 訪問標志的數組
// 圖結構
typedef struct Grapha{
char vertext[MAX_LENGTH]; // 頂點數組
int arc[MAX_LENGTH][MAX_LENGTH]; // 鄰接矩陣
int numVertexts, numEdges; // 頂點數與邊數
} Grapha, *P_Grapha;
// 創建圖
void createMGrah(P_Grapha *G) {
int i, j;
int v, e;
printf("輸入圖的頂點數與邊數:");
scanf("%d %d", &v, &e);
getchar();
(*G) = (P_Grapha)malloc(sizeof(Grapha));
(*G)->numVertexts = v;
(*G)->numEdges = e;
// 初始化頂點
for(i=0; i<v; i++) {
printf("請輸入第%d個頂點:", (i+1));
scanf("%c", &(*G)->vertext[i]);
getchar();
}
// 初始化邊(無向)
for(i=0; i<v; i++) {
for(j=0; j<v; j++) {
(*G)->arc[i][j] = 0;
}
}
// 初始化邊
for(v=0; v<(*G)->numEdges; v++) {
printf("請輸入第%d條邊(Vi,Vj)上的下標i,下標j:\n", (v+1));
scanf("%d %d", &i, &j);
(*G)->arc[i][j] = 1;
(*G)->arc[j][i] = (*G)->arc[i][j] ; // 是無向網圖,對稱矩陣
getchar();
}
// 輸出矩陣
printf("------------ 無向鄰接矩陣 ----------\n");
for(i=0; i<(*G)->numVertexts; i++) {
if(i == 0) {
printf("----%d-",i);
} else {
printf("%d-",i);
}
}
printf("\n");
for(i=0; i<(*G)->numVertexts; i++) {
if(i == 0) {
printf("----%c-",(*G)->vertext[i]);
} else {
printf("%c-",(*G)->vertext[i]);
}
}
printf("\n");
for(i=0; i<(*G)->numVertexts; i++) {
for(j=0; j<(*G)->numVertexts; j++) {
if(j == 0) {
printf("%d-%c|%d-",i,(*G)->vertext[i], (*G)->arc[i][j]);
} else {
printf("%d-",(*G)->arc[i][j]);
}
}
printf("\n"); // 換行
}
}
深度遍歷(DFS算法實現代碼,遍歷二維數組的方式)##
// ============= 深度優先遍歷 二維數組 Start =============
void dfs(P_Grapha G, int i) {
printf("%c ", G->vertext[i]);
visited[i] = TRUE;
int j;
for(j = 0; j<G->numVertexts; j++) {
if(G->arc[i][j] == 1 && !visited[j]) {
dfs(G, j);
}
}
}
void dfsGraph(P_Grapha G) {
int i;
for(i=0; i<G->numVertexts; i++) {
visited[i] = FALSE;
}
for(int i=0; i<G->numVertexts; i++) {
if(!visited[i]) {
dfs(G, i);
}
}
}
主程序
int main(int argc, const char * argv[]) {
P_Grapha g;
createMGrah(&g);
dfsGraph(g);
return 0;
}
深度遍歷(采用棧的形式)##
需要遵循的3個規則:
- 選取當前頂點的鄰接的未訪問到的頂點,標記他,并將其放入棧中;
- 如果不能執行規則1時,如果棧不為空,就從棧中彈出一個頂點,否則執行規則1;
- 重復執行1,2規則,直到不能執行1,2規則時,就完成了整個搜索過程;
實現代碼
// ============= 深度優先遍歷 使用棧 Start =============
// 清空已訪問過得頂點數組
void clearVisit(P_Grapha G) {
int i;
for(i=0; i<G->numVertexts; i++) {
visited[i] = FALSE;
}
}
// 得到與頂點鄰接,且未訪問過得頂點
int getAdjUnivisitedVertex(P_Grapha G, int v) {
int j;
for(j = 0; j<G->numVertexts; j++) {
if(G->arc[v][j] == 1 && visited[j] != TRUE) {
return j;
}
}
return -1;
}
SeqStack *stack;
void dfs_stack(P_Grapha G) {
// 創建棧,并初始化棧
stack = (SeqStack *)malloc(sizeof(SeqStack));
initStack(stack);
clearVisit(G);
// 訪問第一個頂點
printf("%c ", G->vertext[0]);
visited[0] = TRUE;
push(stack, 0);
// 棧不為空
while(isEmpty(stack) == FALSE) {
int p;
int v;
peek(stack, &p);
v = getAdjUnivisitedVertex(G, p); // 得到與頂點p相鄰接的頂點
if(v == -1) { // 沒找到,就從棧中彈出一個頂點
int top;
pop(stack, &top);
} else { // 找到了,打印頂點,并入棧
printf("%c ", G->vertext[v]);
visited[v] = TRUE;
push(stack, v);
}
}
clearVisit(G);
}
// ============= 深度優先遍歷 使用棧 End =============
廣度遍歷(采用隊列的形式)
遵循原則:
- 不斷訪問當前頂點的下一個的頂點,此頂點必須是當前頂點的鄰接點,標記它,并將其插入隊列;
- 如果沒有未訪問的頂點,不能執行1時,則從隊列頭中取一個頂點,使其成為當前頂點,繼續執行1;
- 隊列為空時不能執行2時,表示結束
// ============= 廣度優先遍歷 使用棧 Start =============
Queue *que;
void bfs(P_Grapha G) {
que = (Queue *)malloc(sizeof(Queue));
initQueue(que);
clearVisit(G);
printf("%c ", G->vertext[0]);
visited[0] = TRUE; // 類似層序遍歷
insertQueue(que, 0);
int v1;
int v2;
while(isQueueEmpty(que) == FALSE) {
removeQueue(que, &v1);
while( (v2 = getAdjUnivisitedVertex(G, v1)) != -1 ) { // 不斷獲取當前頂點的鄰接點
printf("%c ", G->vertext[v2]); // 找到鄰接點,放入對列中
visited[v2] = TRUE;
insertQueue(que, v2);
}
}
clearVisit(G);
}