数据结构-图-01

数据结构-图

概念

图(Graph):表示多对多的关系,将线性表和树包含在内

包含:

  • 一组顶点V(vertex)
  • 一组边,通常用E(edge)表示
    • 边是一组定点对:
    • 有向边<v,w>表示从v指向w的边
    • 不考虑重边和自回路

抽象数据类型定义

  • 类型名称:图
  • 数据对象集:非空的有限顶点集和一个有限边集合E组成
  • 操作集:建立、插入、深度优先遍历、最小生成树……

常见术语

  • 有向图

  • 无向图

  • 权重

  • 带权重的图是网络

  • ……

怎么在程序中表示一个图

利用邻接矩阵表示:G [N] [N]——N个顶点0到N-1编号

  • 如果<vi,vj>是G中的边,G [i] [j] = 1,否则为0

  • 在无向图的存储,怎么省空间?

    • 利用一维数组的存储A = {G00,G10,.....,Gn-1 n-1}
    • Gij在A中对应的下标为(i*(i+2)/2+j)
  • 方便计算图的度(和这个顶点有关的边的个数,有向图有入度和出度)

    • 无向图的度:对应行或列非0的个数
    • 有向图:对应行非0的元素个数是“出度”,对应非0元素的个数是“入度”

邻接矩阵 ——有什么不好:但图很稀疏(点多边少)很浪费空间,存完全图是很好的(任意两个点都有边)

利用邻接表表示:为每一个节点开一个指针,对应矩阵每行一个链表,只存非0元素,每个顶点编号链接和它有边的节点,顺序无所谓

图的遍历

  • DFS
  • BFS

DFS

//类似于树的先序遍历
void DFS(vERTEX v)
{
    visited[V] = true;
    for (V中的每个邻接点W)//站在节点位置看其他的节点
        if(!visited[W])//如果节点没有被访问过
			DFS(W); //返回上一层   
}

BFS

广度优先搜索:类似于层序遍历

void BFS ( Vertex V )
{ visited[V] = true;
	Addqueue(V, Q);
	while(!IsEmpty(Q)){
		V = Dequeue(Q);
		for ( V 的每个邻接点 W )
			if ( !visited[W] ) {
			visited[W] = true;
			Addqueue(W, Q);
    	}
	}
}

广度优先是按照一定的规则进行查找
BFS是一圈一圈的按照层次在查找

图不连通怎么办

前面的遍历图中的节点都是联通的,图不连通的时候,那应该怎么办?

我们考虑部分连通的子图,也就是连通分量:无向图的极大连通子图

  • 极大定点数:再加一个顶点就不连通了

  • 极大边数:包含子图中所有顶点相连的所有边。

  • 强连通:有向图中顶点 V 和 W之间存在双向路 径,则称 V 和 W是强连通的

  • 强连通图:有向图中任意两顶点均强连通

  • 强连通分量:有向图的极大强连通子图

将所有的分量都列出来,对每一个顶点的V,如果还没有访问过,就去调用BFS或DFS

例子

007

  • 注意,节点是一个很抽象的概念,边框也是节点
  • 边是007行走的路径
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
struct node
{
    int x,y;
}p[110];
int vis[110];
int flag = 0;
int n,m;
int keyi(int x)//如果可以成功到达岸边
{
    if((p[x].x - m<=-50)||(p[x].x + m>=50)||(p[x].y - m<=-50)||(p[x].y + m >=50))
        return 1;
    return 0;
}
int first(int x)//第一步
{
    int p1 = pow(p[x].x,2);
    int p2 = pow(p[x].y,2);
    int r = (m+7.5)*(m+7.5);
    if(p1+p2<=r)
        return 1;
    return 0;
}
int jump(int x,int y)//能否从一个鳄鱼头跳到另一个鳄鱼头
{
    int p1 = pow(p[x].x - p[y].x,2);
    int p2 = pow(p[x].y - p[y].y,2);
    int r = m*m;
    if(p1+p2<=r)
        return 1;
    return 0;
}
int dfs(int t)
{
    vis[t] = 1;
    if(keyi(t) == 1)
    {
        flag = 1;
    }
    for(int i=0;i<n;i++)
    {
        if(!vis[i]&&jump(t,i))
        {
            flag = dfs(i);
//            if(flag == 1)
//                break;
        }
    }
    return flag;
}

int main()
{
    memset(vis,0,sizeof(vis));
    scanf("%d %d",&n,&m);
    int i;
    for(i=0;i<n;i++)
    {
        scanf("%d %d",&p[i].x,&p[i].y);
    }
    if(m>=42.5)
    {
        printf("Yes\n");
    }
    else
    {
        for(i=0;i<n;i++)
        {
            if(!vis[i]&&first(i))
            {
                dfs(i);
            }
        }
        if(flag == 1)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

六度空间

对每个结点,进行BFS

搜索过程中累计访问的节点数

需要记录“层”数,仅计算6层以内的节点数

void SDS()
{
	for ( each V in G ) {
		count = BFS(V);
		Output(count/N);
	}
}

int BFS ( Vertex V ) 
	visited[V] = true; count = 1;
	level = 0; last = V;
	Enqueue(V, Q);
	while(!IsEmpty(Q)){
		V = Dequeue(Q);
		for ( V 的每个邻接点 W )
			if ( !visited[W] ) {
				visited[W] = true;
				Enqueue(W, Q); count++;
				tail = W;
			}
		if ( V == last ) {
			level++; last = tail;
		}
		if ( level == 6 ) break;
	}
	return count;
}

猜你喜欢

转载自www.cnblogs.com/lingxueqian/p/13382647.html