zoukankan      html  css  js  c++  java
  • 图的遍历

    图是一种比线性表和树略微复杂的数据结构,相比线性表的前驱后继和树的层次关系,图中随意两个元素之间都有可能存在关系。

    图由非空的顶点集合和一个描写叙述顶点之间关系的集合组成,记为 G = (V, E)。可分为 无向图 和 有向图。n个顶点的无向图中,假设随意两个顶点之间有且仅仅有一条边。总的边数为 n(n-1)/2。这种图称为全然图;n个顶点的有向图中,假设随意两个顶点之间有且仅仅有一条边。总的边数为 n(n-1),这种图称为有向全然图

    顶点的度:顶点 v 的度是与该顶点 v 相关联的边的条数。对于有向图,顶点的度分为入度和出度,入度 是以v 为终点的边的条数 ,出度是以v为起点的边的条数。

    顶点的度 =入度+出度。

    权值:图的边可能附有权值,表示一个顶点到还有一个顶点之间的距离时间等实际意义的量。

    带权的图又称为网。

    简单路径:假设从一个顶点到还有一个顶点,路径上全部顶点均不同样。则称该路径为简单路径。

    子图:对于图G1 = (V1, E1)和图 G2 = (V2, E2)。假设V2是V1的子集 且 E2是E1 的子集。则称G2是G1的子图。

    连通图和连通分量: 无向图中,若存在顶点vi 到vj 的路径,则称顶点vi和vj是连通的。假设图中随意一对顶点都是连通的,则称该图是连通图。非连通图的最大连通子图称作连通分量。

    强连通图和强连通分量:有向图中,假设每一对顶点vi和vj之间 从 vi 到 vj 和从vj 到 vi 都存在路径,则称之为强连通图;最大连通子图称为强连通分量。


    图的存储结构:存储图的顶点信息和边的信息。

    每一个顶点都有可能与其它顶点存在联系。全部n个顶点的图 边的关系实质上用一个n*n的矩阵就足以描写叙述。

    两种最主要的图的表示方法有邻接矩阵和邻接链表表示法。

    在稀疏图中,边的条数远小于顶点个数的平方。所以用邻接链表表示比較紧凑,若用邻接矩阵表示会浪费大量空间。

    在稠密图中,边的条数接近顶点个数的平方,倾向于用邻接矩阵表示,由于能够迅速推断随意两个顶点之间是否有边相连。

    邻接链表表示法的一个潜在缺陷是无法高速推断一条边(u,v)是否在图中存在,仅仅能在以u開始的邻接链表中依次搜索节点v。

    而邻接矩阵能够直接推断。可是又存储空间消耗。(无向图的邻接矩阵是对称矩阵。因而能够节省一半空间)


    图的遍历:图的遍历是指从指定的某个顶点出发。依照一定的搜索方法对图中的全部顶点做一次訪问的过程。

    图的遍历过程中,可能存在回溯,所以利用一个数组标记每一个顶点是否被訪问过。

    图的深度优先遍历(DFS):首先訪问初始顶点vi,并将其标记为已被訪问过。然后依次搜索 vi 的每个邻接顶点 vj ,假设vj 没有被訪问过。则以vj 为新的出发点继续深度优先遍历。依次类推,直到訪问全然部顶点。

    图的广度优先遍历(BFS):首先訪问初始顶点 v 。并标记已被訪问过。再訪问初始顶点 v 的全部邻接节点vj ,并标记已被訪问过;再依次訪问vj 的邻接邻接顶点。依次类推,直到全部顶点被訪问完。

    以下举例说明,下图为无向图和其邻接链表存储。

    其实,依据邻接链表能够画出无向图,可是依据无向图却无法确定邻接链表,比如1的第一个指向可能是3 可能是2,这在遍历上有区别。

    以下 分别从顶点1開始进行

    DFS 遍历:

    先訪问顶点1(标记被訪问,下略) 。再查找1的第一个未被訪问邻接顶点3 <在以1开头的链表中查找>

    訪问顶点3,在以3开头的邻接链表查找第一个未被訪问顶点4

    訪问顶点4,在以4开头的邻接链表查找第一个未被訪问顶点7

    訪问顶点7,在以7开头的邻接链表查找第一个未被訪问顶点8

    訪问顶点8,在以8开头的邻接链表查找第一个未被訪问顶点6(7已被訪问过)

    訪问顶点6。在以6开头的邻接链表查找第一个未被訪问顶点(8,4都已被訪问)。查找失败。回溯到上一个顶点8

    在以8开头的邻接链表查找第一个未被訪问顶点 5(7 6 已被訪问)

    訪问顶点5,在以5开头的邻接链表查找第一个未被訪问顶点。查找失败。回溯到上一个顶点6 ,(依次回溯)查找失败,回溯到上一个顶点8;查找失败。回溯到上一个顶点        7;查找失败,回溯到上一个顶点4,查找到第一个未被訪问顶点2.

    訪问顶点2,全部顶点都被訪问过了,结束。

    DFS-------> 1->3->4->7->8->6->5->2

    BFS遍历:

    先訪问顶点1(标记被訪问,下略),再訪问1的全部邻接顶点

    訪问顶点3

    訪问顶点2


    訪问3的全部邻接顶点 4 (1已被訪问) 

    訪问2的全部邻接顶点:无(4,1均已被訪问)


    訪问4的全部邻接顶点:7 6 5 (3,2均已被訪问)


    訪问7的全部邻接顶点:8 (4已被訪问)

    全部顶点都被訪问完结束。

    BFS-------->1->3->2->4->7->6->5->8

    以下直接贴代码:

    #define maximum 10
    
    typedef struct Node
    {
    	int data;//邻接顶点
    	struct Node *next;
    } GraphNode;
    
    GraphNode Graph[maximum]; //顶点数组
    int rear = -1;
    int front = -1;
    //入队
    void AddQueue (int *h, int x)
    {
    	if(rear == maximum-1)
    	{
    		printf("队列已满
    ");
    		return;
    	}
    	rear++;
    	h[rear]=x;
    	return;
    }
    //出队
    int DelQueue(int *h)
    {
    	int e;//e=出队顶点值
    	if(rear==front)
    	{
    		printf("Queue is empty!
    ");
    		return -1;
    	}
    	front++;//front指向队列队头的前一个元素
    	e = h[front];
    	h[front] = 0;
    	return e;
    }
    
    //建立邻接表
    void CreateAdjacentTable(int v1,int v2)
    {
    	GraphNode *newNode,*p;
    	newNode = (GraphNode *)malloc(sizeof(GraphNode));
    	newNode->data = v2;
    	newNode->next = NULL;
    	p = &Graph[v1];//p指向第v1个顶点
    	while(p->next!=NULL)
    		p=p->next;
    	p->next = newNode;//新结点链接在v1最后
    }
    
    //DFS
    void DFS(int *visited, int v)
    {
    	GraphNode *p;
    	printf("%d->",v);
    	visited[v] = 1;//已訪问顶点
    	p = Graph[v].next; //指向第v个顶点的第一个邻接顶点
    	while(p != NULL)
    	{
    		if(visited[p->data] == 0)//假设存在且没有被訪问过
    			DFS(visited,p->data);//递归调用
    		p = p->next;
    	}
    }
    
    //BFS
    void BFS(int *visited, int v, int *Queue)
    {
    	GraphNode *p;
    	AddQueue(Queue,v);//第一个顶点入队列
    	printf("%d->",v);
    	visited[v] = 1;//已被訪问
    	while(front != rear)
    	{
    		v = DelQueue(Queue);//取队头
    		p = Graph[v].next;
    		while(p != NULL)
    		{
    			if(visited[p->data] ==0)
    			{
    				AddQueue(Queue,p->data);
    				visited[p->data] = 1;
    				printf("%d->",p->data);
    			}
    			p = p->next;
    		}
    	}
    }



  • 相关阅读:
    P1182 数列分段`Section II` 二分
    洛谷 P1025 数的划分
    深浅拷贝
    数据的内置方法
    控制流程-if/while/for
    python的基本运算符
    花式赋值
    python的注释
    Python的垃圾回收机制
    变量与常量
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/7387585.html
Copyright © 2011-2022 走看看