数据结构笔记11-图的存储结构及实现

一、邻接矩阵
图的邻接矩阵存储是用一个一维数组存储图中顶点的信息,用一个二维数组(称为邻接
矩阵)存储图中各顶点之间的邻接关系。
假设图G=(V,E)有n个顶点,则邻接矩阵是一个n×n的方阵

1、无向图的邻接矩阵
特点:
主对角线为0且一定是对称矩阵
邻接矩阵的第i行(或第i列)非零元素的个数为顶点i的度
邻接矩阵中相应位置的元素arc[i][j]若为1,则顶点i和j之间存在边
2、有向图的邻接矩阵
特点:
有向图的邻接矩阵不一定对称
邻接矩阵的第i行元素之和为顶点i的出度
邻接矩阵的第i列元素之和为顶点i的入度
邻接矩阵中相应位置的元素arc[i][j]若为1,则顶点i和j之间存在边
 
3、实现
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][MaxSize]; 
    int vertexNum, arcNum; 
};
构造函数
template <class T>
MGraph::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;  //置有边标志    
    }
}
深度优先遍历
int visited[MaxSize];
template <class T>
void MGraph::DFSTraverse(int v){
     cout<<vertex[v]; visited [v]=1;
     for (j=0; j<vertexNum; j++)
         if (arc[v][j]==1 && visited[j]==0)
            DFSTraverse( j );
}
广度优先遍历
int visited[MaxSize];
template <class T>
void MGraph::BFSTraverse(int v){     
    front=rear=-1;   //假设采用顺序队列且不会发生溢出
   int Q[MaxSize]; cout<<vertex[v]; visited[v]=1;  Q[++rear]=v; 
    while (front!=rear)    {
         v=Q[++front];   
         for (j=0; j<vertexNum; j++)
            if (arc[v][j]==1 && visited[j]==0 ) {
                  cout<<vertex[j]; visited[j]=1; Q[++rear]=j;
            }
      }
}
增加一个顶点
template <class T>
void MGraph<T>::InsertVex(int num,T name) { 
 if ( num<0|| num>vertexNum) throw "位置";     
 int row, col, numv; 
 numv = vertexNum-1;
vertexNum++;    
for(int i=numv;i>=num;i--)    vertex[i++]=vertex[i];  
vertex[num]=name;    
 for(row=numv;row>=0;row--)  {所有行上num列之后的列后移,增加一列,
    for(col=numv;col>=num;col--)  arc[row][col+1]=arc[row][col];
     arc[row][num]=0;
  }
  for(row=numv;row>=num;row--) 
        for(col=0;col<=numv+1;col++)  arc[row+1][col]=arc[row][col];    
  for(col=0;col<vertexNum;col++)  arc[num][col]=0; 
}
删除一个顶点
template <class T>   void MGraph<T>::DeleteVex(int pos){
     if ( pos<0||  pos>MaxSize) throw "位置";   
     int row, col;    
     int numv=vertexNum;    
     for(int i=pos;i<numv;i++)   vertex[i]=vertex[i+1];    
     vertexNum--;                            
     for(row=0;row<numv;row++)   { //删除一列
         for(col=pos;col<numv;col++)      arc[row][col]=arc[row][col+1];  
    }
    for(row=pos;row<numv;row++) 
      for(col=0;col<numv;col++)
          arc[row][col]=arc[row+1][col];      
  } 
}
插入一条边
template <class T>
void MGraph<T>::InsertArc(int i, int j)
{
  if ( i>MaxSize||  j>MaxSize) throw "位置";  
  arc[i][j]=1;
  arc[j][i]=1;

删除一条边
template <class T>
void MGraph<T>::DeleteArc(int i, int j)
{
    if ( i>MaxSize||  j>MaxSize) throw "位置";
        arc[i][j]=arc[j][i]=0;   
}


二、邻接表
1、
邻接表有两种结点结构:顶点表结点和边表结点。
顶点表  vertex  firstedge
边表   adjvex  next

vertex:数据域,存放顶点信息。 
firstedge:指针域,指向边表中第一个结点。 
adjvex:邻接点域,边的终点在顶点表中的下标。
next:指针域,指向边表中的下一个结点。

2、实现
struct ArcNode{   
      int adjvex; 
      ArcNode *next;
};

template <class T>
struct VertexNode{
      T vertex;
      ArcNode *firstedge;
};

const int MaxSize=10;    //图的最大顶点数
template <class T>
class ALGraph
{    
   public:
       ALGraph(T a[ ], int n, int e);   
       ~ALGraph;    
       void DFSTraverse(int v);      
       void BFSTraverse(int v);      
   ………
  private:
       VertexNode adjlist[MaxSize];   
       int vertexNum, arcNum;       
};
构造函数 
template <class T>
ALGraph::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;
     }
}
深度优先遍历
template <class T>
void ALGraph::DFSTraverse(int v){        
    cout<<adjlist[v].vertex;  visited[v]=1;
    p=adjlist[v].firstedge;    
    while (p!=NULL)     {
        j=p->adjvex;
        if (visited[j]==0) DFSTraverse(j);
    p=p->next;           
    }
}
广度优先遍历
template <class T>
void ALGraph::BFSTraverse(int v){
   front=rear=-1;   
   cout<<adjlist[v].vertex;    visited[v]=1;   Q[++rear]=v;   
   while (front!=rear)  {
       v=Q[++front];    p=adjlist[v].firstedge;    
       while (p!=NULL)  {
            j= p->adjvex;
            if (visited[j]==0) {
                cout<<adjlist[j].vertex;  visited[j]=1; Q[++rear]=j;
            }
            p=p->next;
       }
    }
}

4、十字链表的结点结构
顶点表结点  vertex  firstin  firstout
边表结点  tailvex  headvex  headlink  taillink
vertex:数据域,存放顶点信息;
firstin:入边表头指针;
firstout:出边表头指针;
tailvex:弧的起点在顶点表中的下标;
headvex:弧的终点在顶点表中的下标;
headlink:入边表指针域;
taillink:出边表指针域。

5、边集数组
利用两个一维数组
一个数组存储顶点信息,另外一个数组存储边及其权。
数组分量包含三个域:边所依附的两个顶点,权值
各边在数组中的次序可以任意。
实现
Struct edge

    int i;
    int j;
    int weight;
}
将邻接矩阵转化成边集数组
edge edges[M];//边的数据结构类型的变量
for ( i = 0; i < G->vexnum; i++) { 
     for (j = 0; j <= G->vexnum; j++)  {
        if (G->arc[i][j] == 1)   {
              edges[k].begin = i;
                edges[k].end = j;
              // edges[k].weight = G->arc[i][j];
               k++;
         }
     }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十只兔子OVO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值