数据结构总结(图)

  图这里存的就是复杂数据了,算法普遍较难,并有很多细节需要经常看。

本章主要内容有,图的逻辑结构,存储结构,连通性,最小生成树,最短路径,AOV,AOE 网等问题。

一,图的逻辑结构

图的部分知识在离散数学已经有所介绍,如有向图顶点度(入度=出度=边数),注意有向图连通也是任意俩点之间连通,不是无向图有边串连所有点的形式。

稀疏图:称边数很少的图为稀疏图;

稠密图:称边数很多的图为稠密图

连通分量:非连通图的极大连通子图称为连通分量。

生成树:n个顶点的连通图G的生成树是包含G全部顶点的一个极小连通子图。

eg:有7个顶点保证图在任何情况下都连通,最少要多少条边?

16条,6个点做完全图,一个点连上

   图的遍历有深度优先搜索(栈辅助)、广度优先搜索(队辅助)两种主要方式。

二,图的存储结构

1,邻接矩阵(数组表达法)

 关于顶点元素的集合一定用顺序存储。

注意无向图在构造邻接矩阵是对称的edge[i][j]=edge[j][i]=1;

DFS针对连通图的遍历
int visited[MaxSize];
template 
void MGraph::DFSTraverse(int v){
     cout<
void MGraph::BFSTraverse(int v){     
    front=rear=-1;
    cout<

2,邻接表(出边表)

对于图的每个顶点vi,将所有邻接于vi的顶点链成一个单链表,称为顶点vi的边表(对于有向图则称为出边表)

所有边表的头指针和存储顶点信息的一维数组构成了顶点表。

struct ArcNode{   
      int adjvex; 
      ArcNode *next;
};

template 
struct VertexNode{
      T vertex;
      ArcNode *firstedge;//初始化时赋空
};
链表的DFS
template 
void ALGraph::DFSTraverse(int v){        
    cout<adjvex;
        if (visited[j]==0) DFSTraverse(j);
    p=p->next;           
    }
}


链表的BFS
template 
void ALGraph::BFSTraverse(int v){
   front=rear=-1;   
   cout<adjvex;
            if (visited[j]==0) {
                cout<next;
       }
    }
}

3,图的其余存储方法还有有向图的十字链表法、无向图的邻接多重表、边集数组。

边集数组:对边依次进行处理时用、最小代价生成树

利用两个一维数组

一个数组存储顶点信息,
另外一个数组存储边及其权

数组分量包含三个域:边所依附的两个顶点,权值

三,最小生成树,连通所有点,权值最小

1,prim算法(加点法,适用稠密图)

int minedge(int lowcost[],int n){
    int m=100,p;
    for(int i=0;ilowcost[i]){
    m=lowcost[i];
    p=i;
    }
    return p;}
Void prime(MGraph G){
    for(int i=1;i

2,kruskal算法(加边法,稀疏图)

使用边集数组,并查集,parent数组判断是否俩点属于同一个连通分量,不属于后一树的parent变前一树的值。

#include
using namespace std;
struct bian                  //边集数组
{
    int from;
    int to;
    int weight;
};
bool cmp(bian a,bian b)           //使sort按权值排序
{
    return a.weight-1)
        ff=parent[ff];
    return ff;
}
int main()
{
    int m,n;
    cin>>n>>m;
    int parent[99];
    int vis[99][99];
    bian eg[99];
    int f=0;
    for(int i=0; i>p;
            if(p!=0&&p!=100&&vis[i][j]==0)
            {
                eg[f].from=i;
                eg[f].to=j;
                eg[f].weight=p;
                vis[i][j]=1;           //无向图
                vis[j][i]=1;
                f++;
            }
        }
    sort(eg,eg+f,cmp);
    int k=0,beginn,endd,countt=0;
    for(k=0; k

四,最短路径

在网图中,最短路径是指两顶点之间经历的边上权值之和最短的路径。

1,dijkstra算法(单元点到其他顶点的最短路径,不能解决负权问题)

路径长度递增,解n-1条路的数值

数组dist[n]每个分量dist[i]表示当前所找到的从始点v到终点vi的最短路径的长度。初态为:

  若从vvi有弧,则dist[i]为弧上权值;否则置dist[i]为∞

数组path[n]path[i]是一个字符串,表示当前所找到的从始点v到终点vi的最短路径。初态为:若从vvi有弧,则path[i]vvi;否则置path[i]空串。

数组s[n]存放源点和已经找到最短路径的终点,其初态为只有一个源点v

#include
#include
#include
using namespace std;
const int MaxSize=10;
const int Max=1000;
class MGraph
{
public:
    MGraph(int n,int e);
    void Dijkstra(int v,int x);
private:
    int vertexnum;
    int arcnum;
    int arc[MaxSize][MaxSize];
    string vertex[MaxSize];
};
MGraph::MGraph(int n,int e){
    vertexnum=n;
    arcnum=e;
    for(int i=0;i>i>>j>>num;
        arc[i][j]=num;
    }
}
void MGraph::Dijkstra(int v,int x){
    string s[Max];
    string path[Max];
    int dist[Max];
    for(int i=0;i>n>>e;
    cin>>v>>x;
    MGraph mg(n,e);
    mg.Dijkstra(v,x);
}

2,floyd算法(任意一对节点之间的最短路径)

邻接矩阵存储,迭代进行

#include
#include
using namespace std;
  int path[99][99];
void judge(int x,int y)
{
     int k=path[x][y];
     if(k==-1) return;
	 judge(x,k);
	 cout<<"v"<>n>>m>>v>>e;
    int dist[99][99];


    for(int i=0;i>x>>y>>z;
    dist[x][y]=z;
    }

    for(int k=0;k

五,有向无环图及其应用。

1,AOV网

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

拓扑序列(前驱后继关系都满足)

若从顶点vivj有一条路径,则在顶点的拓扑序列中顶点vi必在顶点vj之前

拓扑排序:对一个有向图构造拓扑序列的过程称为拓扑排序

#include
using namespace std;
struct bian{
    int hao;
bian *e;
};
struct dian{
int ru;
int  t;
bian *first;
};
int main(){
int v,a;
cin>>v>>a;
dian dd[v+1];
for(int i=1;i<=v;i++)          //边集数组,单存一个入度
{
    dd[i].ru=0;
    dd[i].t=i;
    dd[i].first=NULL;
}
for(int i=0;i>x>>y;
    dd[y].ru++;
    s=new bian;
    s->hao=y;
    s->e=dd[x].first;
    dd[x].first=s;
}

stackp;                 /用栈进行操作
for(int i=v;i>=1;i--)
    if(dd[i].ru==0)
    p.push(i);
while(!p.empty()){
    int j=p.top();
    p.pop();
    cout<<"v"<hao;
        dd[k].ru--;
        if(dd[k].ru==0)
            p.push(k);
        q=q->e;
    }
}



}

2,AOE网

在一个表示工程的带权有向图中,

用顶点表示事件,

用有向边表示活动,

边上的权值表示活动的持续时间,

称这样的有向图叫做边表示活动的网,简称AOE

AOE网中没有入边的顶点称为始点(或源点),没有出边的顶点称为终点(或汇点)。

AOE网的性质:

⑴ 只有在某顶点所代表的事件发生后,从该顶点出发的各活动才能开始

⑵ 只有在进入某顶点的各活动都结束,该顶点所代表的事件才能发生

 

 

关键路径:AOE网中,从始点到终点具有最大路径长度(该路径上的各个活动所持续的时间之和)的路径称为关键路径。

关键活动:关键路径上的活动称为关键活动。

⑴ 事件的最早发生时间ve[k], 指从始点开始到顶点vk的最大路径长度。这个长度决定了所有从顶点vk发出的活动能够开工的最早时间。

⑵ 事件的最迟发生时间vl[k] ,指在不推迟整个工期的前提下,事件vk允许的最晚发生时间。

⑶ 活动的最早开始时间e[i]

⑷ 活动的最晚开始时间l[i]

#include
using namespace std;
struct Edge{                       //构建边的结构体,表式边的俩点,边上事件的最早最晚发生时间
	int from;
	int to;
	int e;
	int l;
};
int ve[99];
int vl[99];

	int vertexnum;
	int adjlist[99][99];   
	int start,end;
	Edge edge[99];  

int main(){
    int v,a;
    int visit[99];
    cin>>v>>a;

    vertexnum=v;


    for(int i=1;i<=v;i++)
        for(int j=1;j<=v;j++)
        adjlist[i][j]=9999;
         for(int i=1;i<=a;i++){
        int x,y,z;
        cin>>x>>y>>z;
        adjlist[x][y]=z;
        edge[i].from=x;
        edge[i].to=y;

    }
    queueq;
    q.push(1);//源点事件入队
	for(int j=1;j<=vertexnum;j++)	{  
		ve[j]=0;	visit[j]=0;	}
	visit[1]=1;
     while(!q.empty())	{
		int i=q.front();       
		q.pop();
		for(int j=1;j<=vertexnum;j++){//计算i的邻接点的ve
			if(adjlist[i][j]!=9999 && ve[i]+adjlist[i][j]>ve[j] ){
				ve[j]=ve[i]+adjlist[i][j];    //算最早,找大的
				if(!visit[j])   
					q.push(j);
				visit[j]=1;
			}
		}
	}
	//for(int i=1;i<=v;i++)
       // cout<

 

你可能感兴趣的:(数据结构)