一、代码实现
#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;
}