图的邻接表表示法及深度搜索与广度搜索

图的深度搜索类似于树的先序遍历,稍微修改即可利用递归实现。

图的广度搜索类似于树的层序遍历,根据数据出入的特性,可以采用队列来实现。队列不使用容器,而采用之前自己写过的队列稍加修改后来使用。

所以文件一共有五个,包括图头文件,图实现文件,队列头文件,队列实现文件,主函数文件。

队列头文件:

#ifndef MYQUEUE_H_  
#define MYQUEUE_H_  
#define QUEUEMAXSIZE 10 //队列数组容量 下标从0-99   
#include <stdio.h>  
#include <malloc.h>  
#include <stdbool.h>  

struct MyQueue;
typedef struct MyQueue * Queue;
typedef int ElementType;

int MyAdd(int number); // 内联函数,用于对组下标越界后的处理,达到下标循环的目的   
Queue InitQueue(void);//构造一个空队列  
bool QueueEmpty(Queue Q);//队列Q是否为空,空返回True   
void DestoryQueue(Queue Q); //从内存中销毁(删除)队列Q  
void ClearQueue(Queue Q); //清空队列Q  
int QueueLength(Queue Q);//返回队列中元素个数  
ElementType GetHead(Queue Q);//返回队列头元素  
void OutQueue(Queue Q);//出队  
void EnQueue(ElementType E, Queue Q);//入队,从队尾插入  

#endif  

队列实现文件:

#include "MyQueue.h"  

struct MyQueue
{
	ElementType * Array; //数组指针   
	int front; //队头下标   
	int rear; //队尾下标   
	int maxsize; //数组容量,用以判断数组是否满   
	int length; //队长,即队中元素个数   
};

int MyAdd(int number) //某种意义上类似于自定义++运算符   
{
	if (number == QUEUEMAXSIZE - 1)
		return 0;
	else
		return number + 1;
}

Queue InitQueue(void)
{
	Queue Q;
	Q = (Queue)malloc(sizeof(struct MyQueue));
	if (Q == NULL)
		printf("Out Of Space!\n");
	Q->Array = (ElementType *)malloc(sizeof(ElementType) * QUEUEMAXSIZE);
	if (Q->Array == NULL)
		printf("Out Of Space!\n");
	Q->front = 0;
	Q->rear = 0;
	Q->length = 0;
	Q->maxsize = QUEUEMAXSIZE;
	return Q;
}

bool QueueEmpty(Queue Q)
{
	if (Q->length == 0)
		return true;
	return false;
}

void DestoryQueue(Queue Q)
{
	free(Q->Array);
	free(Q);
}

void ClearQueue(Queue Q)
{
	Q->front = 0;
	Q->rear = 0;
	Q->length = 0;
}

int QueueLength(Queue Q)
{
	return Q->length;
}

ElementType GetHead(Queue Q)
{
	if (QueueEmpty(Q)){
		printf("Queue is empty!\n");
		return 0; //因为函数必须要有返回值,故返回零   
	}
	return Q->Array[Q->front];
}

void OutQueue(Queue Q)
{
	if (QueueEmpty(Q))
		printf("Queue is empty!\n");
	else{
		Q->front = MyAdd(Q->front);
		Q->length--;
	}
}

void EnQueue(ElementType E, Queue Q)
{
	if (Q->length == Q->maxsize)
		printf("Queue is full!\n");
	else{
		Q->Array[Q->rear] = E;
		Q->rear = MyAdd(Q->rear);
		Q->length++;
	}
}

图头文件:

#ifndef ADJACENCYMATRIX_H
#define ADJACENCYMATRIX_H

#define FLOWOVER -1
#define MAX_VERTEX_NUM 8

struct AdjacencyMatrix;//邻接表
struct VecNodeOfAdjacencyMatrix;//顶点列表头结点
struct ArcNodeOfAdjacencyMatrix;//图的边
typedef struct AdjacencyMatrix AdjMatrix;
typedef struct VecNodeOfAdjacencyMatrix VecNode;
typedef struct ArcNodeOfAdjacencyMatrix * AdjNode;
typedef char ElemType;

struct VecNodeOfAdjacencyMatrix
{
	ElemType elem;//该点的数据域
	int degree;//该点的度
	AdjNode next;//指向下一条边的指针
};

struct AdjacencyMatrix
{
	VecNode list[MAX_VERTEX_NUM];//顶点列表
	int vexnum;//图的总节点数
	int arcnum;//图的总边数
};

struct ArcNodeOfAdjacencyMatrix
{
	int number;//该边的弧头
	int weight;//边的权重
	AdjNode next;//指向下一条边的指针
};

void CreatAdjMatrix(AdjMatrix & A);//初始化一个图
bool AddVex(AdjMatrix & A, ElemType E, int D);//输入图,节点值,节点度,添加节点,成功返回true
static AdjNode tailOfList(AdjNode N);//若顶点节点后面有边节点,输入该边节点地址,返回横向链最后一条边的地址
bool AddArc(AdjMatrix & A, int tailOfArc, int headOfArc, int W);//输入图,弧头尾编号,弧权重,添加弧,成功返回true
void PrintAdjMatrix(AdjMatrix A);//输入图,打印出图
void DepthFirstSearch(AdjMatrix A, int v);//图的深度优先搜索
static void DFS(AdjMatrix A, int v);
void BreadthFirstSearch(AdjMatrix A, int v);//图的广度优先搜索

#endif

图实现文件:

#include <stdlib.h>
#include <stdio.h>
#include "AdjacencyMatrix.h"
#include "MyQueue.h"

static int visited[MAX_VERTEX_NUM];

void CreatAdjMatrix(AdjMatrix & A)
{
	for (int i = 0; i < MAX_VERTEX_NUM; i++){
		A.list[i].elem = -1;
		A.list[i].degree = 0;
		A.list[i].next = NULL;
		A.vexnum = 0;
		A.arcnum = 0;
	}
}

bool AddVex(AdjMatrix & A, ElemType E, int D)
{
	A.list[A.vexnum].elem = E;
	A.list[A.vexnum].degree = D;
	A.list[A.vexnum].next = NULL;
	A.vexnum++;

	return true;
}

static AdjNode tailOfList(AdjNode N)
{
	while (N->next != NULL){
		N = N->next;
	}
	return N;
}

bool AddArc(AdjMatrix & A, int tailOfArc, int headOfArc, int W)
{
	if (tailOfArc < A.vexnum && headOfArc < A.vexnum){
		if (A.list[tailOfArc].next == NULL){
			A.list[tailOfArc].next = (AdjNode)malloc(sizeof(struct ArcNodeOfAdjacencyMatrix));
			if (A.list[tailOfArc].next == NULL){
				exit(FLOWOVER);
			}
			A.list[tailOfArc].next->next = NULL;
			A.list[tailOfArc].next->number = headOfArc;
			A.list[tailOfArc].next->weight = W;
		}
		else{
			AdjNode tempNode = tailOfList(A.list[tailOfArc].next);
			tempNode->next = (AdjNode)malloc(sizeof(struct ArcNodeOfAdjacencyMatrix));
			if (tempNode->next == NULL){
				exit(FLOWOVER);
			}
			tempNode->next->next = NULL;
			tempNode->next->number = headOfArc;
			tempNode->next->weight = W;
		}
		A.arcnum++;
		return true;
	}
	else{
		printf("请先输入节点!\n");
		return false;
	}
}

void PrintAdjMatrix(AdjMatrix A)
{

}

void DepthFirstSearch(AdjMatrix A, int v)
{
	int visited[MAX_VERTEX_NUM];
	for (int i = 0; i < MAX_VERTEX_NUM; i++){
		visited[i] = 0;
	}

	if (visited[v] == 0)
		DFS(A, v);
}

static void DFS(AdjMatrix A, int v)
{
	printf("%c ", A.list[v].elem);
	visited[v] = 1;
	AdjNode tempNode = A.list[v].next;
	while (tempNode != NULL){
		if (visited[tempNode->number] == 0){
			DFS(A, tempNode->number);
		}
		tempNode = tempNode->next;
	}
}

void BreadthFirstSearch(AdjMatrix A, int v)
{
	int visited[MAX_VERTEX_NUM];
	int u;
	int flag = 0;//用于标记是否所有点都被访问过了
	for (int i = 0; i < MAX_VERTEX_NUM; i++){
		visited[i] = 0;
	}
	Queue Q;
	Q = InitQueue();
	if (visited[v] == 0){
		printf("%c ", A.list[v].elem);
		visited[v] = 1;
		flag++;
		u = v;
		EnQueue(v, Q);
		while (flag != A.vexnum){
			AdjNode tempNode = A.list[u].next;
			while (tempNode != NULL){
				if (visited[tempNode->number] == 0){
					visited[tempNode->number] = 1;
					flag++;
					printf("%c ", A.list[tempNode->number].elem);
					EnQueue(tempNode->number, Q);

				}
				tempNode = tempNode->next;
			}
			u = GetHead(Q);
			OutQueue(Q);
		}
	}
	
}

主函数文件:

#include <stdlib.h>
#include <stdio.h>
#include "AdjacencyMatrix.h"

int main()
{
	AdjMatrix testAdj;
	CreatAdjMatrix(testAdj);

	AddVex(testAdj, 'a', 2);
	AddVex(testAdj, 'b', 3);
	AddVex(testAdj, 'c', 3);
	AddVex(testAdj, 'd', 4);
	AddVex(testAdj, 'e', 2);
	AddVex(testAdj, 'f', 2);

	AddArc(testAdj, 0, 2, 1);
	AddArc(testAdj, 0, 1, 1);
	AddArc(testAdj, 1, 0, 1);
	AddArc(testAdj, 1, 2, 1);
	AddArc(testAdj, 1, 3, 1);
	AddArc(testAdj, 2, 0, 1);
	AddArc(testAdj, 2, 1, 1);
	AddArc(testAdj, 2, 3, 1);
	AddArc(testAdj, 3, 1, 1);
	AddArc(testAdj, 3, 2, 1);
	AddArc(testAdj, 3, 4, 1);
	AddArc(testAdj, 3, 5, 1);
	AddArc(testAdj, 4, 3, 1);
	AddArc(testAdj, 4, 5, 1);
	AddArc(testAdj, 5, 3, 1);
	AddArc(testAdj, 5, 4, 1);

	printf("深度优先搜索:");
	DepthFirstSearch(testAdj, 0);
	printf("\n");
	printf("广度优先搜索:");
	BreadthFirstSearch(testAdj, 0);
	printf("\n");

	system("pause");
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值