一、代码实现
#include <stdio.h> #include <string.h> #include <malloc.h> #define MAX_VEX_NUM 20 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 int visited[MAX_VEX_NUM]; typedef int status; typedef int q_elemtype; int g_print_stack = 0; int ve[MAX_VEX_NUM]; int vl[MAX_VEX_NUM]; /* 邻接表的数据结构 */ enum GraphyKind { DG, DN, UDG, UDN }; struct ArcNode { int adjvex_no; int arcinfo[MAX_VEX_NUM]; struct ArcNode *nextarc; }; struct VNode { char data[3]; struct ArcNode * firstarc; }; struct ALGraphy { int vexnum; int arcnum; enum GraphyKind kind; struct VNode *HeadNode; }; /* 链队列的数据结构 */ struct QNode { q_elemtype data; struct QNode *next; }; struct linked_queue { struct QNode *front; struct QNode *rear; }; typedef int s_elemtype; //存放图的顶点序号 #define STACK_INIT_SIZE 128 /* 顺序栈的数据结构 */ struct stack { s_elemtype *base; s_elemtype *top; int stack_size; }; status init_stack(struct stack *S) { (*S).base = (s_elemtype*)malloc(sizeof(s_elemtype) * STACK_INIT_SIZE); if (!(*S).base) { printf("%s: malloc failed\n", __FUNCTION__); return ERROR; } (*S).top = (*S).base; (*S).stack_size = STACK_INIT_SIZE; return OK; } status get_top_of_stack(struct stack S, s_elemtype *e) { if (S.base == S.top) { return ERROR; } else { (*e) = *(S.top - 1); } return OK; } status stack_empty(struct stack S) { return (S.base == S.top? 1 : 0); } void push_stack(struct stack *S, s_elemtype e) { *((*S).top++) = e; if (1 == g_print_stack) { printf("push %c\n", e); } } void pop_stack(struct stack *S, s_elemtype *e) { (*e) = *(--(*S).top); if (1 == g_print_stack) { printf("pop %c\n", *e); } } status init_queue(struct linked_queue *Q) { (*Q).front = (*Q).rear = NULL; return OK; } int queue_empty(struct linked_queue Q) { if (!Q.rear && !Q.front) { return 1; } else { return 0; } } status enqueue(struct linked_queue *Q, q_elemtype elem) { struct QNode *p; p = (struct QNode*)malloc(sizeof(struct QNode)); if (!p) { return ERROR; } p->data = elem; p->next = NULL; if (queue_empty(*Q)) { (*Q).front = (*Q).rear = p; } else { (*Q).rear->next = p; (*Q).rear = p; } return OK; } status dequeue(struct linked_queue *Q, q_elemtype *elem) { struct QNode *p; if (queue_empty(*Q)) { return ERROR; } else { p = (*Q).front; (*elem) = p->data; (*Q).front = p->next; if (!p->next) { (*Q).rear = NULL; } free(p); return OK; } } int get_first_adjvex(struct ALGraphy G, int vex_no) { if (G.HeadNode[vex_no].firstarc) { return G.HeadNode[vex_no].firstarc->adjvex_no; } return -1; } int get_next_adjvex(struct ALGraphy G, int vex_no, int w) { struct ArcNode *p; p = G.HeadNode[vex_no].firstarc; while (p && p->adjvex_no != w) { p = p->nextarc; } if (p && p->nextarc) { return p->nextarc->adjvex_no; } else { return -1; } } void visit(struct ALGraphy G, int vex_no) { printf("visit %s\n", G.HeadNode[vex_no].data); } void DFS(struct ALGraphy G, int vex_no) { int i; visited[vex_no] = TRUE; visit(G, vex_no); for (i = get_first_adjvex(G, vex_no); i != -1; i = get_next_adjvex(G, vex_no, i)) { if (!visited[i]) { DFS(G, i); } } } void DFS_traverse(struct ALGraphy G) { int i; for (i = 0; i < G.vexnum; i++) { visited[i] = FALSE; } i = 0; /* !不要误解这个for循环,这个只是针对非连通图而设置,对于连通图,只须DFS(G,0)即可 */ //for (i = 0; i < G.vexnum; i++) //{ // if (!visited[i]) // { DFS(G, i); // } //} } void BFS_traverse(struct ALGraphy G) { int i; q_elemtype vex_no = 0; struct linked_queue Q; for (i = 0; i < G.vexnum; i++) { visited[i] = FALSE; } init_queue(&Q); /* !这里没有考虑非连通图的情况,反而便于读者理解,理解了后就很容易去理解非连通图的处理了 */ visited[vex_no] = TRUE; visit(G, vex_no); enqueue(&Q, vex_no); while (!queue_empty(Q)) { dequeue(&Q, &vex_no); for (i = get_first_adjvex(G, vex_no); i != -1; i = get_next_adjvex(G, vex_no, i)) { if (!visited[i]) { visited[i] = TRUE; visit(G, i); enqueue(&Q, i); } } } } void find_ingree(struct ALGraphy G, int ingree[]) { struct ArcNode *p; int i; int k; for (i = 0; i < G.vexnum; i++) { for (p = G.HeadNode[i].firstarc; p; p = p->nextarc) { k = p->adjvex_no; ingree[k]++; } } } /*------------------------------------------------------------------------ * * 图的拓扑排序 * * 用栈S来表示零入度栈,处理ve[i], 返回拓扑逆序栈T给函数critical_path使用,* * count用来判断AOV或AOE是否有环,如果有环,那环所包括的节点入度 * * 不可能变为0,因此不可能进栈S,count就不会自加了 * *------------------------------------------------------------------------ */ status TP_sort(struct ALGraphy G, struct stack *T) { s_elemtype e; struct ArcNode *p; struct stack S; int count = 0; int ingree[MAX_VEX_NUM] = {0}; int i; int k; find_ingree(G, ingree); init_stack(&S); for (i = 0; i < G.vexnum; i++) { if (!ingree[i]) { push_stack(&S, i); } } init_stack(T); for (i = 0; i < G.vexnum; i++) { ve[i] = 0; } while (!stack_empty(S)) { pop_stack(&S, &e); push_stack(T, e); count++; for (p = G.HeadNode[e].firstarc; p; p = p->nextarc) { k = p->adjvex_no; if (!--ingree[k]) { push_stack(&S, k); } /* 把从起始点到k点的路径最大值赋给ve[k]*/ if (ve[e] + p->arcinfo[k] > ve[k]) { ve[k] = ve[e] + p->arcinfo[k]; } } } if (count < G.vexnum) { printf("===== count = %d, vexnum = %d ==== \n", count, G.vexnum); return ERROR; } else { return OK; } } /* 求取关键路径 */ status critical_path(struct ALGraphy G) { struct stack T; struct ArcNode *p; int e; int i; int k; int ee; int el; if (!TP_sort(G, &T)) { printf("There is a circle in the graphy\n"); return ERROR; } for (i = 0; i < G.vexnum; i++) { vl[i] = ve[G.vexnum - 1]; } while (!stack_empty(T)) { pop_stack(&T, &e); for (p = G.HeadNode[e].firstarc; p; p = p->nextarc) { k = p->adjvex_no; if (vl[e] > (vl[k] - p->arcinfo[k])) { vl[e] = vl[k] - p->arcinfo[k]; } } } for (i = 0; i < G.vexnum; i++) { for (p = G.HeadNode[i].firstarc; p; p = p->nextarc) { k = p->adjvex_no; ee = ve[i]; el = vl[k] - p->arcinfo[k]; if (ee == el) /* 又把=号当成==,调试半天,哎! */ { printf("arc(%d->%d) is critical activity, ee = %d, el =%d\n", i, k, ee, el); } } } } status create_graphy(struct ALGraphy *G) { int i; int v; struct ArcNode *pArcNode; char name[3] = {0}; printf("please input vexnum:"); scanf("%d", &(*G).vexnum); printf("please input graphy kind:(0(DG),1(DN),2(UDG),3(UDN):"); scanf("%d", &(*G).kind); (*G).arcnum = 0; (*G).HeadNode = (struct VNode*)malloc(sizeof(struct VNode) * (*G).vexnum); if (!(*G).HeadNode) { printf("%s: malloc failed\n", __FUNCTION__); return ERROR; } for (i = 0; i < (*G).vexnum; i++) { sprintf(name, "v%d", i); strcpy((*G).HeadNode[i].data, name); printf("data:%s\n",(*G).HeadNode[i].data); (*G).HeadNode[i].firstarc = NULL; printf("please input v%d's last adjvex(or input -1 to exit the loop):", i); scanf("%d", &v); while (v != -1) { pArcNode = (struct ArcNode*)malloc(sizeof(struct ArcNode)); if (!pArcNode) { printf("%s: malloc failed\n", __FUNCTION__); return ERROR; } printf("please input arcinfo(v%d->v%d):", i, v); scanf("%d", &pArcNode->arcinfo[v]); (*G).arcnum++; pArcNode->adjvex_no = v; pArcNode->nextarc = (*G).HeadNode[i].firstarc; (*G).HeadNode[i].firstarc = pArcNode; printf("please input v%d's another front adjvex(or input -1 to exit the loop):", i); scanf("%d", &v); } } return OK; } void print_graphy(struct ALGraphy G) { int i; printf("vexnum:%3d\n", G.vexnum); printf("arcnum:%3d\n", G.arcnum); printf("kind: %3d\n", G.kind); for (i = 0; i < G.vexnum; i++) //for循环老喜欢加;号阿,影响程序调试,罪过! { //printf("Head data:%s\n", G.HeadNode[i].data); } //其余信息读者根据需要自己添加把,TODO } int main(void) { struct ALGraphy G; (void)create_graphy(&G); print_graphy(G); printf("Depth First Search:\n"); DFS_traverse(G); printf("Breadth First Search:\n"); BFS_traverse(G); printf("Critical Path:\n"); critical_path(G); return 0; }