數據結構——圖

1 圖的定義數組

  多對多的數據結構,由頂點的非空集合和頂點之間的邊的集合組成;數據結構

1.1 圖的概念spa

  數據元素3d

    在線性表中稱爲元素;在樹中稱爲結點、在圖中稱爲頂點指針

  數據元素集合code

    在線性表中能夠沒有元素稱爲空表;在樹中能夠沒有結點稱爲空樹;在圖中不能沒有頂點,即頂點集合不能爲空blog

  數據元素之間的關係get

    在線性表中稱爲線性關係;在樹中稱爲層次關係;在圖中稱爲邊的關係,邊的集合能夠爲空;it

1.2 圖的種類io

   

   

   

1.3 圖的概念

   

   

   

   

   

   

   

2 圖的抽象數據類型

  ADT圖

  data:頂點的非空又窮集合和邊的有限集合

operation
  creatGraph(G,V,VR) //按照頂點集合V和邊的集合VR構建圖G
  destroyGraph(G) //銷燬圖G
  locateGraph(G,V)//若圖G中存在頂點V,則返回V在圖中的位置
  getVex(G,V)//返回圖G中,頂點V的值
  putVex(G,V,x)//將圖G中頂點V賦值爲x
  firstAdjVex(G,V)//獲取圖G中頂點V的一個鄰接頂點
  nextAdjVex(G,V,W)//獲取圖G中頂點V相對於頂點W的下一個鄰接頂點
  insertVex(G,V)//在圖G中添加一個頂點V
  deleteVex(G,V)//刪除圖G中的頂點V,及相關的邊
  insertArc(G,V,W)//在圖G中添加弧<V,W>
  deleteArc(G,V,W)//在圖G中刪除弧<V,W>
  DFSTraverse(G)//圖G的先深搜索
  HFSTraverse(G)//圖G的先廣搜索
endADT

3 圖的存儲結構

3.1 鄰接矩陣

  由兩個數組表示圖;一個是存儲頂點的數組,一維數組;一個是存儲邊或弧的數組,二維數組;

   

   

3.2 鄰接表

  由數組和鏈表表示圖;一個是存儲頂點的數組,每一個數組元素由頂點、第一條邊指針組成;還有一個存儲邊或弧的鏈表;

  結點結構

     

   

   

   

3.3 十字鏈表

  由一維數組和鏈表表示圖;一個是存儲頂點的一維數組,每一個數組元素由頂點、入邊結點指針、出邊結點指針組成;還有一個存儲邊或弧的十字鏈表;

   

3.4 鄰接多重表

  由數組和鏈表表示圖;一個存儲頂點的數組;還有一個是存儲邊的十字鏈表

   

3.5 邊集數組

  由二個一維數組表示圖;一個是存儲頂點的數組;另外一個是存儲邊或弧的數組,每一個數組元素由弧頭、弧尾、權組成;

   

  

4 圖的遍歷

  從圖中某一頂點出發,使圖中其他頂點都被訪問到,且僅被訪問一次的方法

  具體方法是經過定義一個數組visited[n],其中:

    n:表示圖中頂點的個數

    visited[i]的值,(n>i>=0)

    值爲0表示該頂點未被訪問過;

    值爲1表示該頂點已被訪問過;

  圖的遍歷方法

    深度優先搜索

    廣度優先搜索

4.1 深度優先搜索

4.1.1 鄰接矩陣

   

typedef int VType;  //頂點的數據類型
typedef int EType;  //邊的數據類型
#define VSIZE 100;  //最大頂點數
typedef struct AdjMGraph  
{
  VType vex[VSIZE];  //頂點數組
  EType arc[VSIZE][VSIZE];  //邊弧數組
  int VNum;
  int ENum;
}AdjMGraph;

/*
建立鄰接矩陣
*/
void creatAdjMGraph(AdjMGraph *g)
{
  printf("輸入頂點個數:");
  scanf("%d",&g->VNum);
  printf("輸入頂點間的邊數:");
  scanf("%d",&g->ENum);
  for(int i=0;i<g->VNum;i++)
    scanf("%d",&g->vexs[i]);
  for(int i=0;i<g->VNum;i++)
    for(int j=0;j<g->VNum;j++)
      g->arc[i][j]=0;
  for(int k=0;k<g->ENum;k++)
  {
    printf("輸入邊(vi,vj)的下標i,j");
    int i,j;
    scanf("%d %d",&i,&j);
    g->arc[i][j]=g->arc[j][i]=1;
  }
}

int visited[VSIZE];
void (*visitFunc)(VType t);

void print(VType t)
{
  printf("%d\n",t);
}

void DFS(AdjMGraph g,int i)
{
  visited[i]=1;
  visitFunc(g.vexs[i]);
  for(int j=0;j<g.VNum;j++)
  {
    if(g.arc[i][j]==1 && visited[j]==0)
    {
      DFS(g,j);
    }
  }
}

void DFSTraverse(AdjMGraph g,void (*vf)(VType t))
{
  visitFunc=vf;
  for(int i=0;i<g.VNum;i++)
  {
    visited[i]=0;
  }
  for(int i=0;i<g.VNum;i++)
  {
    if(visited[j]==0)
    {
      DFS(g,j);
    }
  }
}

void main()
{
  AdjMGraph g;  //定義鄰接矩陣圖
  creatAdjMGraph(&g);  //建立鄰接矩陣圖
  DFSTraverse(g,print); //遍歷鄰接矩陣圖
}

4.1.2 鄰接表

   

typedef int VType;  //頂點的數據類型
typedef int EType;  //邊的數據類型
#define VSIZE 100;  //最大頂點數
typedef struct ENode  //邊鏈表結點
{
  int v; //頂點下標
  struct ENode *next; //下一個頂點的指針
}ENode;

typedef struct VNode //頂點表結點
{
  VType data; //頂點中的數據
  struct VNode *first; //第一個邊鏈表結點的指針
}VNode;

typedef struct AdjMGraph
{
  VType vex[VSIZE];  //頂點數組
  int VNum; //頂點數
  int ENum; //邊數
}AdjMGraph;

/*
建立鄰接表
*/
void creatAdjMGraph(AdjMGraph *g)
{
  printf("輸入頂點個數:");
  scanf("%d",&g->VNum);
  printf("輸入頂點間的邊數:");
  scanf("%d",&g->ENum);
  for(int i=0;i<g->VNum;i++)
  {
    printf("輸入頂點%d的數據:",i);
    scanf("%d",&g->vexs[i].data);
    g->vexs[i].first=NULL;
  }
  for(int k=0;k<g->ENum;k++)
  {
    printf("輸入邊(vi,vj)的下標i,j");
    int i,j;
    scanf("%d %d",&i,&j);
    ENode *p=(ENode*)malloc(sizeof(ENode));
    p->v=j;
    p->next=g->vexs[i].first;
    g->vexs[i].first=p;
    p=(ENode*)malloc(sizeof(ENode));
    p->v=i;
    p->next=g->vexs[i].first;
    g->vexs[i].first=p;
  }
}

int visited[VSIZE];
void (*visitFunc)(VType t);

void print(VType t)
{
  printf("%d\n",t);
}

void DFS(AdjMGraph g,int i)
{
  visited[i]=1;
  visitFunc(g.vexs[i].data);
  ENode *p=g.vexs[i].first;
  while(p)
  {
    if(visited[p->v]==0)
      DFS(g,p->v);
    p=p->next;
  }
}

void DFSTraverse(AdjMGraph g,void (*vf)(VType t))
{
  visitFunc=vf;
  for(int i=0;i<g.VNum;i++)
  {
    visited[i]=0;
  }
  for(int i=0;i<g.VNum;i++)
  {
    if(visited[j]==0)
    {
      DFS(g,j);
    }
  }
}

void main()
{
  AdjMGraph g;  //定義鄰接矩陣圖
  creatAdjMGraph(&g);  //建立鄰接矩陣圖
  DFSTraverse(g,print); //遍歷鄰接矩陣圖
}

4.2 廣度優先搜索

4.2.1 鄰接矩陣

   

typedef int VType;  //頂點的數據類型
typedef int EType;  //邊的數據類型
#define VSIZE 100;  //最大頂點數
typedef struct AdjMGraph  
{
  VType vex[VSIZE];  //頂點數組
  EType arc[VSIZE][VSIZE];  //邊弧數組
  int VNum; //頂點個數
  int ENum;  //邊弧的個數
}AdjMGraph;

/*
建立鄰接矩陣
*/
void creatAdjMGraph(AdjMGraph *g)
{
  printf("輸入頂點個數:");
  scanf("%d",&g->VNum);
  printf("輸入頂點間的邊數:");
  scanf("%d",&g->ENum);
  for(int i=0;i<g->VNum;i++)
    scanf("%d",&g->vexs[i]);
  for(int i=0;i<g->VNum;i++)
    for(int j=0;j<g->VNum;j++)
      g->arc[i][j]=0;
  for(int k=0;k<g->ENum;k++)
  {
    printf("輸入邊(vi,vj)的下標i,j");
    int i,j;
    scanf("%d %d",&i,&j);
    g->arc[i][j]=g->arc[j][i]=1;
  }
}

void print(VType t)
{
  printf("%d\n",t);
}

void BFSTraverse(AdjMGraph g,void(*visitFunc)(VType t))
{
  int visited[VSIZE];
  for(int i=0;i<g.VNum;i++)
  {
    visited[i]=0;
  }
  Queue q;
  initQueue(&q);
  for(int i=0;i<g.VNum;i++)
  {
    if(visited[i]==0)
    {
      visited[i]=1;
      visitFunc(g.vexs[i]);
      enQueue(&q,i);
      while(QueueEmpty(q)==0)
      {
        deQueue(&q,&i);
        for(int j=0;j<g.VNum;j++)
        {
          if(g.arc[i][j]==1 && visited[j]==0)
          {
            visited[j]==1;
            visitFunc(g.vexs[j]);
            enQueue(&q,j);
          }
        }
      }
    }
  }
}

4.2.2 鄰接表

 

typedef int VType;  //頂點的數據類型
typedef int EType;  //邊的數據類型
#define VSIZE 100;  //最大頂點數
typedef struct ENode  //邊鏈表結點
{
  int v; //頂點下標
  struct ENode *next; //下一個頂點的指針
}ENode;

typedef struct VNode //頂點表結點
{
  VType data; //頂點中的數據
  struct VNode *first; //第一個邊鏈表結點的指針
}VNode;

typedef struct AdjMGraph
{
  VType vex[VSIZE];  //頂點數組
  int VNum; //頂點數
  int ENum; //邊數
}AdjMGraph;

/*
建立鄰接表
*/
void creatAdjMGraph(AdjMGraph *g)
{
  printf("輸入頂點個數:");
  scanf("%d",&g->VNum);
  printf("輸入頂點間的邊數:");
  scanf("%d",&g->ENum);
  for(int i=0;i<g->VNum;i++)
  {
    printf("輸入頂點%d的數據:",i);
    scanf("%d",&g->vexs[i].data);
    g->vexs[i].first=NULL;
  }
  for(int k=0;k<g->ENum;k++)
  {
    printf("輸入邊(vi,vj)的下標i,j");
    int i,j;
    scanf("%d %d",&i,&j);
    ENode *p=(ENode*)malloc(sizeof(ENode));
    p->v=j;
    p->next=g->vexs[i].first;
    g->vexs[i].first=p;
    p=(ENode*)malloc(sizeof(ENode));
    p->v=i;
    p->next=g->vexs[i].first;
    g->vexs[i].first=p;
  }
}

void print(VType t)
{
  printf("%d\n",t);
}

void DFSTraverse(AdjMGraph g,void(*visitFunc)(VType t))
{
  int visited[VSIZE];
  for(int i=0;i<g.VNum;i++)
  {
    visited[i]=0;
  }
  Queue q;
  initQueue(&q);
  for(int i=0;i<g.VNum;i++)
  {
    if(visited[i]==0)
    {
      visited[i]=1;
      visitFunc(g.vexs[i].data);
      enQueue(&q,i);
      while(QueueEmpty(q)==0)
      {
        deQueue(&q,&i);
        ENode *p=g.vexs[i].first;
        while(p)
        {
          if(visited[p->v]==0)
          {
            visited[p->v]==1;
            visitFunc(g.vexs[p->v].data);
            enQueue(&q,p->v);
          }
          p=p->next;
        }
      }
    }
  }
}

void main()
{
  AdjMGraph g;  //定義鄰接矩陣圖
  creatAdjMGraph(&g);  //建立鄰接矩陣圖
  DFSTraverse(g,print); //遍歷鄰接矩陣圖
}
相關文章
相關標籤/搜索