数据结构,运用邻接表建立有向图,并进行深度优先遍历、广度广度优先遍历(c语言)

运用邻接表建立有向图,并进行深度优先遍历、广度广度优先遍历(c语言)

自认为深度和广度遍历的思路能够帮助大家更好地理解

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAX_VERTEX_NUM 20
int visited[MAX_VERTEX_NUM];

typedef int Status;
typedef char VertexType;
typedef int QElemType;

typedef struct ArcNode{
	 int adjvex;
	struct ArcNode *nextarc;   //链表的结点 
}ArcNode;

typedef struct VNode{
	VertexType data;       //表的元素    
	ArcNode *firstarc;   //指向下一个结点,即首个邻接点 
}VNode,AdjList[MAX_VERTEX_NUM];

typedef struct{
	AdjList vertices;
	int vexnum,arcnum;      //图的结点数和弧数 
}ALGraph; 

队列 (用于广度优先搜索)

//队列 (用于广度优先搜索) 
typedef struct QNode{
	QElemType date;
	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) return ERROR;
	Q->front->next=NULL;
	return OK;
}

//入队
Status EnQueue(LinkQueue *Q,QElemType e)   
{
	QueuePtr s=(QueuePtr)malloc(sizeof(QNode));
	if(!s) return ERROR;
	s->date=e;
	Q->rear->next=s;
	s->next=NULL;
	Q->rear=s;
	return OK;
	
}
//出队
Status DeQueue(LinkQueue *Q,QElemType *e)
{
	QueuePtr p;
	if(Q->front==Q->rear)  return ERROR;
	p=Q->front->next;
	*e=p->date;
	Q->front->next=p->next;
	if(p==Q->rear){
		Q->rear=Q->front;
	} 
	free(p);
	return OK;
}

Status QueueEmpty(LinkQueue Q)
{
	if(Q.front==Q.rear)  
		return OK;
	else	
 	return ERROR;
 	 
}//队列 
//定位节点的位置
int LocateVexs(ALGraph A,VertexType ch)
{
	int v;
	for(v=0;v<A.vexnum;v++)
	{
		if(A.vertices[v].data==ch)
			return v;
	}
	return -1;
}

//建立图
Status CreatALGraph(ALGraph *A)
{
	int i;
	int m,n;
	VertexType a,b;
	printf("请输入图的结点数和边的个数:");
	scanf("%d%d",&(A->vexnum),&(A->arcnum));
	printf("请输入结点元素:");
	getchar();
	for(i=0;i<A->vexnum;i++)
	{
		scanf("%c",&((A->vertices[i]).data));
		A->vertices[i].firstarc=NULL;
	}
		
	printf("请输入边:\n点-点\n");
	for(i=0;i<A->arcnum;i++)
	{
		ArcNode *s;
		ArcNode *p;
		s=(ArcNode*)malloc(sizeof(ArcNode));
		if(!s) return ERROR;
		getchar();
		scanf("%c-%c",&a,&b);
		m=LocateVexs(*A,a);
		n=LocateVexs(*A,b);
		s->adjvex=n;
		s->nextarc=NULL;
		if((A->vertices[m]).firstarc==NULL)
			(A->vertices[m]).firstarc=s;
		else{
			p=(A->vertices[m]).firstarc;
			while(p->nextarc)
			{
				p=p->nextarc;
			}
			p->nextarc=s;
		}
		
	}
	 return OK;
	
}

找出第一个邻接点

int FirstAdjVex(ALGraph A,int i)
{
	if(i<0||i>=A.vexnum)	return -1;
	if(!A.vertices[i].firstarc) return -1;   //当结点没有首节点是,应该返回-1; 【注】之前一直错这个 
	return A.vertices[i].firstarc->adjvex;	
}
int NextAdjVex(ALGraph A,int i,int j)
{
	ArcNode *p=A.vertices[i].firstarc;
	if(!p) return -1;
	if(i<0||i>=A.vexnum) return -1;
	if(j<0||j>=A.vexnum) return -1;
	while((p->adjvex!=j)&&(p->nextarc))
	{
		p=p->nextarc;
	}
	if(p&&(p->nextarc)) return (p->nextarc)->adjvex;
	return -1;
}

深度遍历

//深度遍历 
void DFS(ALGraph A,int v)
{
	int w;
	printf("%c",A.vertices[v].data);   //输出第一个元素
	visited[v]=1;                      //每输出一个元素则将visited[v] 赋值为1;
	w=FirstAdjVex(A,v);   //深度优先即为首先输出第一邻接点,同时临界
	                    //链表的表示第一个邻接点的表示与后面的不同
	while(w!=-1)
	{
		if(visited[w]==0)
			DFS(A,w);
		w=NextAdjVex(A,v,w);    //当上面的递归结束后,进行到头结点后的结点
//		printf("\nw=%d\n",w);    
	}
}  

//深度排序,思路为:运用递归,将各个结点的第一个邻接顶点
                             
void DFSTraverse(ALGraph A)
{
	int v;
	for(v=0;v<A.vexnum;v++)	
		visited[v]=0; 
	for(v=0;v<A.vexnum;v++)     //用来控制所有点能够被访问,主要用来使非连通图
								//的各个子图全部被访问
	{ 
		if(visited[v]==1)
		continue;      
			DFS(A,v);      //如果没有被访问,则将v作为输出的第一个元素;
	 } 	
}
 

广度遍历

void BFSTraverse(ALGraph A)
{
	int w,v;
	LinkQueue Q;
	int e;
	InitQueue(&Q);
	for(v=0;v<A.vexnum;v++)
		visited[v]=0;
	for(v=0;v<A.vexnum;v++)   //保证输出所有的结点,因为可能图部位可达图 
	{
		if(visited[v]==1) continue;
		printf("%c",A.vertices[v].data);
		visited[v]=1;
		EnQueue(&Q,v);   //先将子图的首结点入队; 
		while(!QueueEmpty(Q))   //输出最大子图; 
		{
			DeQueue(&Q,&e);   //然后将队的头结点出队; 
			w=FirstAdjVex(A,e);    //求出队的头结点的下一个 
			for(;w!=-1;w=NextAdjVex(A,e,w))    //循环将下一个元素全部输出完,并全部入队; 
			{
				if(visited[w]==1) continue;
				printf("%c",A.vertices[w].data);
				visited[w]=1;
				EnQueue(&Q,w);
			 } 		
		}
	}
}

主函数

int main()
{
	ALGraph G;
	CreatALGraph(&G);
	printf("%d\n",FirstAdjVex(G,1));
	printf("%d\n",NextAdjVex(G,1,2));
	printf("深度优先:\n"); 
	DFSTraverse(G);
	printf("\n广度优先:\n");
	BFSTraverse(G);
	printf("\n");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值