自定义遍历算法:深度+广度


A custom traversal algorithm (一种自定义遍历算法:深度+广度)


前言

随着深度优先和广度优先算法的不断使用,一种新的自定义算法被提出,本文就介绍了本算法的内容。

一、自定义算法简介

It traverses the graph depth-first and breadth-next 。

For example ,

The proposed depth-first and breadth-next traversal is to follow the order illustrated below:
在这里插入图片描述

What you notice here is that the traversal is depth-first until it reaches a leaf node. When it does, then the next node it chooses is the next child of the root where the traversal began. In the words, the choice is similar to breadth-first where the children of the root are picked in order. Such a traversal finds applicability in scheduling where clustering dependent jobs may be desirable for performance (e.g., to facilitate in-memory communication than messages).

即先深度遍历后广度遍历,每次遍历需要遍历完全后,再进行下一次遍历,故被称为 “depth-first and breadth-next” 。

二、源代码

编译环境为Dev(以上述题目为例):

1.定义数据结构

//邻接表存储图
typedef struct ArcNode
{
	int verIndex;       
	struct ArcNode *nextarc;   //指向下一条弧的指针 
	int *info;           //该弧相关的信息的指针,如权值 
}ArcNode; 

typedef struct VNode
{
	int data;     //顶点信息 
	ArcNode *firstarc;   //指向第一条依附于该顶点的弧指针 
}VNode, AdjList[20];



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

//创建用于广度优先遍历的队列
typedef struct QNode
{
	int data;              //队列中节点数据类型 
	struct QNode *qnext;
}QNode, *PQNode;

typedef struct Queue
{
	PQNode front;
	PQNode rear;
}Queue, *PQueue;

2.完整代码

代码如下(示例):

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

/* 图的深度优先遍历和广度优先遍历 */
//邻接表存储图
typedef struct ArcNode
{
	int verIndex;       
	struct ArcNode *nextarc;   //指向下一条弧的指针 
	int *info;           //该弧相关的信息的指针,如权值 
}ArcNode; 

typedef struct VNode
{
	int data;     //顶点信息 
	ArcNode *firstarc;   //指向第一条依附于该顶点的弧指针 
}VNode, AdjList[20];



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

//创建用于广度优先遍历的队列
typedef struct QNode
{
	int data;              //队列中节点数据类型 
	struct QNode *qnext;
}QNode, *PQNode;

typedef struct Queue
{
	PQNode front;
	PQNode rear;
}Queue, *PQueue;

//初始化一个空队列 
PQueue initQueue()
{
	PQueue pqueue = (PQueue)malloc(sizeof(Queue));
	PQNode pqnode = (PQNode)malloc(sizeof(QNode));
	if (pqnode == NULL)
	{
		printf("Queue head space request failed!\n");
		exit(-1);
	}
	pqueue->front = pqueue->rear = pqnode;
	pqnode->qnext = NULL;
	return pqueue;
}

//队尾入队
void enQueue(PQueue pqueue, int data)
{
	PQNode pqnode = (PQNode)malloc(sizeof(QNode));
	if (pqnode == NULL)
	{
		printf("Queue node request failed!\n");
		exit(-1);
	}
	pqnode->data = data;
	pqnode->qnext = NULL;
	pqueue->rear->qnext = pqnode;
	pqueue->rear = pqnode;
}
//判断队列是否为空
bool isEmpty(PQueue pqueue)
{
	if (pqueue->front == pqueue->rear)
		return true;
	return false;
}
//队头出队
int deQueue(PQueue pqueue)
{
	if (isEmpty(pqueue))
	{
		printf("The queue is empty\n");
		exit(-1);
	}

	PQNode pqnode = pqueue->front->qnext;
	pqueue->front->qnext = pqnode->qnext;
	if (pqnode == pqueue->rear)
		pqueue->rear = pqueue->front;
	int data = pqnode->data;
	free(pqnode);
	return data;

}

//确定图中索引位置编号(Index) 
int vexIndex(ALGraph alg, int v)
{
	int i;
	for (i = 0; i<alg.vexnum; i++)
	{
		if (alg.vertices[i].data == v)
			return i;
	}
	return -1;
}

//创建完整的邻接表
void createALGraph(ALGraph *alg)
{
	int i, j, v, k;
	printf("Enter the number of vertices and edges of the graph:\n");
	scanf("%d %d", &(*alg).vexnum, &(*alg).arcnum);
	printf("Enter the node value (or label) of the vertex:\n");
	//fflush(stdin); 
	getchar();
	for (i = 0; i<(*alg).vexnum; i++)
	{
		printf("Enter the %d vertex label:", i);
		scanf("%d", &(*alg).vertices[i].data);
		(*alg).vertices[i].firstarc = NULL;
		// fflush(stdin);             //fflush(stdin)  
		getchar();                   // getchar()清除上次输入的缓存 
	}

	printf("Enter the edge information of the graph:\n");
	int v1, v2;
	i = 0; j = 0;
	ArcNode *s, *p;
	for (k = 1; k<=(*alg).arcnum; k++)
	{
		printf("Enter the two nodes of the %d edge: v1 v2 with the label:", k);
		scanf("%d %d", &v1, &v2);
		i = vexIndex((*alg), v1);
		
		j = vexIndex((*alg), v2);
		printf("Index i: %d\tj: %d\n", i, j);
		//开辟弧的空间并判断 
		p = (ArcNode*)malloc(sizeof(ArcNode));
		p->verIndex = j;
		p->nextarc = NULL;          
		if ((*alg).vertices[i].firstarc == NULL)
		{
			(*alg).vertices[i].firstarc = p;
		}
		else
		{
			s = (*alg).vertices[i].firstarc;
			while (s->nextarc != NULL)
				s = s->nextarc;
			s->nextarc = p;
		}
	}
}

bool travalorNot[20];  //标记结点是否被遍历过,如果没有被遍历为flase,是为true;



void D_B(ALGraph alg)//先深度、后广度
{

	printf("Depth-first, breadth-next traversal sequence by the vertices label:\n");
	PQueue pqueue = initQueue();
	ArcNode *p;
	int i;
	int v;
	for (i = 0; i<alg.vexnum; i++)
		travalorNot[i] = false;
	for (i = 0; i<alg.vexnum; i++)
	{
		if (!travalorNot[i])
		{
			enQueue(pqueue, i);//进队
			while (!isEmpty(pqueue))
			{
				v = deQueue(pqueue);//v出去
				int tempv = v;
				//printf("出去的v:%d\n",v);

			AA:
				for (p = alg.vertices[v].firstarc; p != NULL; p = p->nextarc)
				{
					if (!travalorNot[p->verIndex])
					{
						//travalorNot[p->verIndex] = true;
						enQueue(pqueue, p->verIndex);
					}
				}
				if (!travalorNot[tempv])
				{
					printf("%d ", alg.vertices[tempv].data);//输出v
					travalorNot[tempv] = true;
				}

				if (alg.vertices[tempv].firstarc != NULL)
				{
					ArcNode * temp = alg.vertices[tempv].firstarc;//深度
					v = temp->verIndex;
					tempv = v;
					//printf("test2:%d",v);
					goto AA;
				}
			}


		}
	}


	

}

void printFormat(ALGraph alg)//像题目格式一样输出所有邻接表
{
	printf("Output the adjacency list the same as the title format:\n[\t");
	for (int i = 0; i < alg.vexnum; i++)
	{
		printf("[ %d ",alg.vertices[i].data);
		ArcNode * p = alg.vertices[i].firstarc;
		while (true)
		{
			if (p != NULL)
			{
				printf(" %d ", p->verIndex);
				p = p->nextarc;
			}
			else
			{
				break;
			}
			
		}
		if (i < alg.vexnum - 1)
		{
			printf("],\n\t");
		}
		else
		{
			printf("]\n];\n");
		}
		
	}
}

int main() {
	ALGraph alg;
	createALGraph(&alg);   //创建无向图 

	printFormat(alg);

	D_B(alg);


	return 0;
}

三、运行结果

在这里插入图片描述
Index表明顶点的序号(我们发现每条边 j 的序号的并集则是邻接列表中除第1列外其他列的点的序号集合)

总结

在结果中,生成了此有向图的邻接列表,第1列为顶点的value,而后几列则为顶点的序号。(它们代表的意义不同)
最后打印出先深度再广度的遍历顺序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值