数据结构笔记——第六章 图




6.1 图的逻辑结构

6.1.1 图的定义和基本术语

数据元素称为顶点。

1、 图的定义

图是由顶点的有穷非空集合和顶点之间边的集合组成。

如果图的任意两个顶点之间的边都是无向边,则称该图为无向图;否则称有向图。

2、 图的基本术语

简单图

若不存在顶点到其自身的边,且同一条边不重复出现,则称为简单图。

无向完全图:任意两个顶点之间都存在边。含n个顶点的无向完全图有n*(n-1)/2条边。

有向完全图:任意两顶点之间都存在方向互为相反的两条弧。含n个顶点的有向完全图有n*(n-1)条边。

无向图中顶点的度:依附于该顶点的边的个数。具有n个顶点e条边 ,度=2e.

有向图中顶点的度:以该顶点为弧头的弧的个数。具有n个顶点e条边,度=e.

简单路径:顶点不重复出现的路径。

简单回路:除了第一个顶点和最后一个顶点之外,其余顶点不重复出现的回路。

子图:


连通图和连通分量


生成树、生成森林

6.1.2 图的抽象数据类型定义

6.1.3图的遍历操作

1、深度优先遍历

1)访问顶点V

2)从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历

3)重复上述两步,直至图中所有的顶点都被访问到。


2、 广度优先遍历

(1) 访问顶点v

(2) 依次访问v的各个未被访问的邻接点v1,,,vk

(3) 分别从v1,,,vk出发依次访问它们未被访问的邻接点,并使“先被访问顶点的邻接点”先于“后被访问顶点的邻接点”被访问。直至图中所有的顶点都被访问到。


6.2 图的存储结构及实现

6.2.1邻接矩阵


C++中的模板机制

Const int MaxSize=10;

Template<class T>

Class MGraph

{

   Public:

      MGraph(T a[],int n,int e);

      ~MGraph(){ }

      Void DFSTraverse(int v);

      Void BFSTraverse(int v);

   Private:

      T vertex[MaxSize];

      Int arc[MaxSize];

      Int vertexNum,arcNum;

}

1、 构造函数

template<class T>

MGraph<T>::MGraph(T a[],int n,int e)

{


vertexNum=n;arcNum=e;

for(i=0;i<vertexNum;i++)

vertex[i]=a[i];

for(i=0;i<vertexNum;i++)

for(j=0;j<vertexNum;j++)

arc[i][j]=0;

for(k=0;k<arcNum;k++)

{

cin>>i>>j;

arc[i][j]=1;arc[j][i]=1;

}

}

2、深度优先遍历

template<class T>

void MGraph<T>::DFSTraverse(int v)

{

cout<<vertex[v];visited[v]=1;

for(int j=0;j<vertexNum;j++)

if(arc[v][j]==1&&visited[j]==0)

DFSTraverse(j);

}

3、广度优先遍历

template<class T>

void MGraph<T>::BFSTraverse(int v)

{

int front=-1,rear=-1;

cout<<vertex[v];visited[v]=1;Q[++rear]=v;

while(front!=rear)

{

v=Q[++front];

for(int j=0;j<vertexNum; j++)

if(arc[v][j]==1&&visited[j]==0)

{

cout<<vertex[j];visited[j]=1;Q[++rear]=j;

}

}

}

6.2.2邻接表

邻接表是一种顺序存储与链接存储相结合的存储方法,类似于树的孩子链表表示方法。

存在两种节点结构:


C++语言中的结构体类型描述上述结点。

struct ArcNode

{

int adjvex;

ArcNode *next;

};

template <class T>

struct VertexNode

{

T vertex;

ArcNode *firstedge;

};

C++语言中的类实现基于邻接表存储结构下图的抽象数据类型定义:

class ALGraph

{

public:

ALGraph(T a[],int n,int e);

~ALGraph();

void DFSTraverse(int v);

void BFSTraverse(int v);

private:

VertexNode<T>adjlist[MaxSize];

int vertexNum,arcNum;

};

1、构造函数算法ALGraph


template<class T>

ALGraph<T>::ALGraph(T a[],int n,int e)

{

vertexNum=n;arcNum=e;

for(i=0;i<vertexNum;i++)

{

adjlist[i].vertex=a[i];

adjlist[i].firstedge=NULL;

}

for(k=0;k<arcNum;k++)

{

cin>>i>>j;

s=new ArcNode;s->adjvex=j;

s->next=adjlist[i].firstedge;

adjlist[i].firstedge=s;

}

}

2、深度优先遍历算法DFSTraverse

template<class T>

void ALGraph<T>::DFSTraverse(int v)

{

ArcNode *p=NULL;int j;

cout<<adjlist[v].vertex;vistited[v]=1;

p=adjlist[v].firstedge;

while(p!=NULL)

{

j=p->adjvex;

if(visited[j]==0)  DFSTraverse(j);

p=p->next;

}

}

3、广度优先遍历算法BFSTraverse

template<class T>

void ALGraph<T>::BFSTraverse(int v)

{

int Q[MaxSize];

int front=-1,rear=-1;

ArcNode *p=NULL;

cout<<adjlist[v].vertex;visited[v]=1;Q[++rear]=v;

while(front!=rear)

{

v=Q[++front];

p=adjlist[v].firstedge;

while(p!=NULL)

{

int j=p->adjvex;

if(visited[j]==0)

{

cout<<adjlist[j].vertex;visited[j]=1;Q[++rear]=j;

}

p=p->next;

}

}

}

6.3 最小生成树

G=V,E)是一个无向连通网,生成树上各边的权值之和称为该生成树的代价,在G的所有生成树中,代价最小的生成树称为最小生成树。

6.3.1 Prim 算法


Void Prim(MGraph G)

{

   For(i=1;i<G.vertexNum;i++)

   {

       shortEdge[i] .lowcost=G.arc[0][i];

       shortEdge[i].adjvex=0;

   }

shortEdge[0].lowcost=0;

For(i=1;i<G.vertexNum;i++)

{

K=MinEdge(shorEdge,G.vertexNum)

Cout<<”(“<<k<<shortEdge[k].adjvex<<”)”<<shortEdge[k].lowcost;

shortEdge[k].lowcost=0;

For(j=1;j<G.vertexNum;j++)

If  G.arc[k][j]<shortEdge[j].lowcost

{

   shortEdge[j].lowcost=G.arc[k][j];

   shortEdge[j].adjvex=k;

}

}

}

6.3.2 Kruskal 算法


Void Kruskal(EdgeGraph G)

{

For(i=0;i<G.vertexNum;i++)

  Parent[i]=-1;

For(num=0,i=0;i<G.edgeNum;i++)

{

    Vex1=FindRoot(parent,G.edge[i].from);

    Vex2=FindRoot(parent,G.edge[i].to);

    If(vex1!=vex2)

    {

       Cout<<”(“<<G.edge[i].from<<G.edge[i].to<<”)”<<endl;

       Parent[vex2]=vex1;

       Num++;

       If(num==n-1) return;

    }

}

}

Int FindRoot(int parent[],int v)

{

   T=v;

   If(parent[t]>-1) t=parent[t];

   Return t;

}

6.4 最短路径

最短路径是指两顶点之间经历的边数最小的路径,路径上的第一个顶点称为源点,最后一个顶点称为终点。

Dijkstra算法


Void Dijkstra(MGraph G,int v)

{

   For(i=0;iG.vertexNumi++

   {

       Dist[i]=G.arc[v][i];

       If(dist[i]!=ɷ)path[i]=G.vertex[v]+G.vertex[i];

       Else path[i]=” “;

   }

   S[0]=v;

   Dist[v]=0;

   Num=1;

   While(num<G.vertexNum)

   {

      For(k=0,i=0;i<G.vertexNum;i++)

      If((dist[i]!0)&&(dist[i]<dist[k])) k=i;

      Cout<<dist[k]<<path[k];

      S[num++}=k;

      For(i=0;i<G.vertexNum;i++)

      If(dist[i]>dist[k]+G.arc[k][i])

      {

         dist[i]=dist[k]+G.arc[k][i];

         path[i]=path[k]+G.vertex[i];

      }

     Dist[k]=0;

}

}

6.4.2  Floyd 算法


6.5 有向无环图

6.5.1 AOV 网与拓扑排序

在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,称这样的有向图为顶点表示活动的网,简称AOV网。

基本思想是:

 1)从AOV网中选择一个没有前驱的顶点并且输出它;

 2) 从AOV网中删去该顶点,并且删去所有以该顶点为尾的弧;

 3)重复上述两步,直到全部顶点都被输出,或AOV网中不存在没有前驱的顶点。

伪代码:


拓扑排序算法TopSort

  void TopSort(ALGraph G)

  {

      top=-1;count=0;

      for(i=0;i<G.vertexNum;i++)

        if(G.adjlist[i].in==0)s[++top]=i;

      while(top=-1)

      {

          j=s[top--];

           cout<<G.adjlist[j].vertex;count++;

           p=G.adjlist[j].firstedge;

           while(p!=NULL)

          {

               k=p->adjvex;

               G.adjlist[k].in--;

               if(G.adjlist[k].in==0) S[++top]=k;

               p=p->next;

          }

       }

       if(count<G.vertexNum) cout<<"有回路";

    }

本章总结





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值