#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_NODE_NUM 10
typedef int ElemType;
typedef enum {DG,UDG} GKind;
typedef void (*VISIT)(ElemType); //定义一个函数指针的类型VISIT, 指向一个"返回类型为void, 参数类型为ElemType"的函数
//队列结构
typedef struct Node
{
ElemType data;
struct Node* next;
}Node;
typedef struct Queue
{
Node* front, *tail;
}Queue;
//图结构
typedef struct OtherNode
{
int index;
struct OtherNode* next;
}OtherNode;
typedef struct HeadNode
{
ElemType data;
OtherNode* otnode;
}HeadNode;
typedef struct AdjListGraph
{
HeadNode headvec[MAX_NODE_NUM];
int vexnum, arcnum;
GKind kind;
}AdjListGraph;
void InitQueue(Queue* Q)
//初始化队列
{
Node* head = (Node*)malloc(sizeof(Node));
head->data=0;
head->next = NULL;
Q->front = head;
Q->tail = head;
}
int IsEmpty(Queue* Q)
//判断队列是否为空
{
if(Q->tail == Q->front)
return 1;
else
return 0;
}
void Enqueue(Queue* Q, ElemType v)
{
Node* node = (Node*)malloc(sizeof(Node));
node->data = v;
node->next = NULL;
Node* p = (Node*)malloc(sizeof(Node));
p = Q->front;
while(p->next!=NULL)
p = p->next;
//此时p指向队列的最后一个结点
p->next = node;
//修改队尾指针
Q->tail = node;
}
ElemType Dequeue(Queue* Q)
{
if(!IsEmpty(Q))
{
Node* node = (Node*)malloc(sizeof(Node));
node = Q->front->next;
Q->front->next = node->next;
if(node->next ==NULL) //说明出队的这个元素是最后一个元素
Q->tail = Q->front; //令队尾指针指向队头
return node->data;
}
else
{
printf("queue is empty");
return -1000;
}
}
int Locate(AdjListGraph* G, ElemType v)
{
for(int i = 0; i<=G->vexnum-1; i++)
{
if(G->headvec[i].data == v)
return i;
}
return -1000;
}
ElemType FirstAdjVex(AdjListGraph* G, ElemType v)
//返回顶点v在G中的第一个邻接顶点
{
int i = Locate(G, v);
if(G->headvec[i].otnode!=NULL)
{
int pos = G->headvec[i].otnode->index; //第一个邻接顶点的索引
return G->headvec[pos].data;
}
else
return -1000;//不存在邻接顶点
}
ElemType NextAdjVex(AdjListGraph* G, ElemType v, ElemType w)
//,w是顶点v的一个邻接顶点, 返回顶点v的下一个(相对于w的)邻接顶点
{
int i = Locate(G, v);
OtherNode* p = G->headvec[i].otnode; //p指向顶点v的第一个邻接顶点
ElemType AdjVexData = G->headvec[p->index].data;
while(AdjVexData != w)
{
p = p->next;
AdjVexData = G->headvec[p->index].data;
}
//此时指针p指向w顶点
p = p->next;
if(p) //如果w顶点后面还有顶点
return G->headvec[p->index].data;
else //如果w顶点就是最后一个顶点
return -1000;
}
void AddNode(AdjListGraph* G, int i, OtherNode* p_new)
//给索引为i的顶点的链表中增加一个结点p_new
{
if(G->headvec[i].otnode)
//当前顶点已经有至少一个邻接结点了, 需要把新结点加在这个结点后面
{
OtherNode* tmp = G->headvec[i].otnode;
while(tmp->next)
tmp = tmp->next;
//此时,tmp指向当前顶点的链表中最后一个结点
tmp->next = p_new;
}
else
{
G->headvec[i].otnode = p_new;
}
}
void CreateAdjListGraph(AdjListGraph* G)
{
//初始化顶点向量headvec
for(int i = 0; i<=G->vexnum-1; i++)
{
printf("第%d个顶点的值为:",i);
scanf("%d", &G->headvec[i].data);
G->headvec[i].otnode = NULL;
}
//输入边的信息,对每个顶点创建链表
for(int arc = 0; arc<=G->arcnum-1; arc++)
{
ElemType v1, v2, w;
printf("第%d条边的第一个顶点,第二个顶点,权值 分别为:",arc);
scanf("%d%d%d",&v1, &v2, &w);
//得到两个顶点各自在顶点向量中的索引
int i = Locate(G, v1);
int j = Locate(G, v2);
OtherNode* p_ij = (OtherNode*)malloc(sizeof(OtherNode));
//若是有向图, 则第i个顶点的链表要新加一个指向j的node
p_ij->index = j;
p_ij->next = NULL;
AddNode(G, i, p_ij);
//若是无向图, 则还需要在顶点j的链表上增加一个指向i的结点
if(G->kind == UDG)
{
OtherNode* p_ji = (OtherNode*)malloc(sizeof(OtherNode));
p_ji->index = i;
p_ji->next = NULL;
AddNode(G, j, p_ji);
}
}
printf("has created AdjListGraph.\n");
}
void visit(ElemType s)
{
printf("visited %d, \n",s);
}
void BroadFirstSearch(AdjListGraph* G, VISIT visit_fn)
{
//广度优先搜索
int visited[G->vexnum];
//初始化visited数组
for(int i = 0; i<=G->vexnum-1; i++)
{
visited[i] = 0;
}
for(int i = 0; i<=G->vexnum-1; i++)
{
if(!visited[i])
{
//队列用于存放当前顶点下的所有被访问过的节点, 每次访问一个节点,就将其放入队列
Queue Q;
InitQueue(&Q);
//访问当前顶点
visit_fn(G->headvec[i].data);
visited[i] = 1;
Enqueue(&Q, G->headvec[i].data);
if(!IsEmpty(&Q))
printf("queue is not empty.\n");
while(!IsEmpty(&Q))
{
ElemType u = Dequeue(&Q);
printf("%d 节点出队,",u);
for(ElemType w=FirstAdjVex(G,u); w>=0; w = NextAdjVex(G, u, w))
{
int pos = Locate(G, w);
if(!visited[pos])
{
visit_fn(w);
visited[pos] =1;
Enqueue(&Q, w);
printf("%d 节点入队,",w);
}
}
}
}
else
printf("all the nodes are visited.\n");
}
return;
}
void dfs(AdjListGraph* G, ElemType v, int visited[], VISIT visit_fn)
{
visit_fn(v);
int pos = Locate(G, v);
visited[pos] = 1;
for(ElemType w = FirstAdjVex(G, v); w>=0; w = NextAdjVex(G, v, w))
{
int pos = Locate(G, w);
if(!visited[pos]) //说明这个邻接结点还没被访问过
dfs(G, w, visited, visit_fn);
}
}
void DepthFirstSearch(AdjListGraph* G, VISIT visit_fn)
{
int visited[G->vexnum];
for(int i = 0; i<=G->vexnum-1; i++)
{
visited[i] = 0;
}
for(int i = 0; i<=G->vexnum-1; i++)
{
if(!visited[i]) //说明当前结点未被访问过
{
ElemType v = G->headvec[i].data;
dfs(G,v, visited, visit_fn);
}
}
}
int main()
{
VISIT visit_fn;
visit_fn = visit;
AdjListGraph G;
G.vexnum = 6;
G.arcnum = 5;
CreateAdjListGraph(&G);
BroadFirstSearch(&G, visit_fn);
DepthFirstSearch(&G, visit_fn);
//队列结构测试
/*
Queue Q;
InitQueue(&Q);
printf("is empty is:%d, ",IsEmpty(&Q));
Enqueue(&Q,1);
printf("is empty is:%d, ",IsEmpty(&Q));
Enqueue(&Q,2);
printf("is empty is:%d, ",IsEmpty(&Q));
ElemType b;
b = Dequeue(&Q);
printf("Dequeue is:%d, ",b);
b = Dequeue(&Q);
printf("Dequeue is:%d, ",b);
b = Dequeue(&Q);
printf("Dequeue is:%d, ",b);*/
}
图的深度优先和广度优先遍历
最新推荐文章于 2024-05-09 11:45:55 发布