手记

c/c++ 图的创建及图的相关函数(链表法)

c/c++ 图的创建及图的相关函数(链表法)

图的概念

  • 图由点和线组成

  • 知道了图中有多少个点,和哪些点之间有线,就可以把一张图描绘出来

  • 点之间的线,分有方向和无方向

创建图

创建图,实际就是创建出节点,和节点之间的线。

下面的代码实现了上面的图的创建

graph_link.h

#ifndef __graph_link__
#define __graph_link__
#include <stdio.h>
#include <malloc.h>#include <assert.h>
#include <memory.h>
#define default_vertex_size 10#define T char//边的结构typedef struct Edge{
  //顶点的下标
  int idx;  //指向下一个边的指针
  struct Edge* link;}Edge;//顶点的结构typedef struct Vertex{
  //顶点的值
  T data;  //边
  Edge* adj;
}Vertex;//图的结构typedef struct GraphLink{
  int MaxVertices;  int NumVertices;  int NumEdges;

  Vertex* nodeTable;
}GraphLink;
//初始化图void init_graph_link(GraphLink* g);
//显示图void show_graph_link(GraphLink* g);
//插入顶点void insert_vertex(GraphLink* g, T v);
//插入边尾插void insert_edge_tail(GraphLink* g, T v1, T v2);
//插入边头插void insert_edge_head(GraphLink* g, T v1, T v2);
//删除边void remove_edge(GraphLink* g, T v1, T v2);
//删除顶点void remove_vertex(GraphLink* g, T v);
//销毁图void destroy_graph_link(GraphLink* g);
//取得指定顶点的第一个后序顶点int get_first_neighbor(GraphLink* g, T v);
//取得指定顶点v1的临街顶点v2的第一个后序顶点int get_next_neighbor(GraphLink* g, T v1, T v2);#endif

graph_link.c

#include "graph_link.h"//初始化图void init_graph_link(GraphLink* g){
  g->MaxVertices = default_vertex_size;
  g->NumVertices = g->NumEdges = 0;

  g->nodeTable = (Vertex*)malloc(sizeof(Vertex) * g->MaxVertices);
  assert(NULL != g->nodeTable);  for(int i = 0; i < g->MaxVertices; ++i){
    g->nodeTable[i].adj = NULL;
  }
}//显示图void show_graph_link(GraphLink* g){  
if(NULL == g)return; 
 for(int i = 0; i < g->NumVertices; ++i){   
  printf("%d %c->", i, g->nodeTable[i].data);
    Edge* p = g->nodeTable[i].adj;    while(NULL != p){     
     printf("%d->", p->idx);
      p = p->link;
    }    printf(" NULL\n");
  }
}//插入顶点void insert_vertex(GraphLink* g, T v){ 
 if(g->NumVertices >= g->MaxVertices)return;
  g->nodeTable[g->NumVertices++].data = v;
}//查找顶点的indexint getVertexIndex(GraphLink* g, T v){ 
 for(int i = 0; i < g->NumVertices; ++i){   
  if(v == g->nodeTable[i].data)return i;
  }  return -1;
}//创建边void buyEdge(Edge** e, int idx){
  Edge* p = (Edge*)malloc(sizeof(Edge));
  p->idx = idx;
  p->link = NULL;  if(NULL == *e){
    *e = p;
  }  else{
    Edge* tmp = *e;    while(tmp->link != NULL){
      tmp = tmp->link;
    }
    tmp->link = p;
  }
}//插入边(尾插)void insert_edge_tail(GraphLink* g, T v1, T v2){  
int p1 = getVertexIndex(g, v1);  
int p2 = getVertexIndex(g, v2); 
 if(p1 == -1 || p2 == -1)return;
  
  buyEdge(&(g->nodeTable[p1].adj), p2);
  g->NumEdges++;
  buyEdge(&(g->nodeTable[p2].adj), p1);
  g->NumEdges++;

}//插入边(头插)void insert_edge_head(GraphLink* g, T v1, T v2){  
int p1 = getVertexIndex(g, v1); 
 int p2 = getVertexIndex(g, v2);  
if(p1 == -1 || p2 == -1)return;

  Edge* p = (Edge*)malloc(sizeof(Edge));
  p->idx = p2;
  p->link = g->nodeTable[p1].adj;
  g->nodeTable[p1].adj = p;
  
  p = (Edge*)malloc(sizeof(Edge));
  p->idx = p1;
  p->link = g->nodeTable[p2].adj;
  g->nodeTable[p2].adj = p;  
}//删除边int remove_edge_(Edge** p, int i){  if(NULL == *p)return -1;
  Edge* f;  //判断第一个边是否是目标边
  if((*p)->idx == i){    //删除第一条边
    f = *p;
    *p = (*p)->link;    free(f);    return 0;
  }

  Edge* tmp = *p;  while(tmp->link != NULL && tmp->link->idx != i){
    tmp = tmp->link;
  }  //没有找到边
  if(tmp->link == NULL){    return -1;
  }  //找到边
  else{
    f = tmp->link;
    tmp->link = tmp->link->link;    free(f);    return 0;
  }

}void remove_edge(GraphLink* g, T v1, T v2){  int p1 = getVertexIndex(g, v1);  int p2 = getVertexIndex(g, v2);  if(p1 == -1 || p2 == -1)return;  int r = remove_edge_(&(g->nodeTable[p1].adj), p2);  if(r == 0){
    g->NumEdges--;
    remove_edge_(&(g->nodeTable[p2].adj), p1);
    g->NumEdges--;
  }

}//删除顶点void remove_vertex(GraphLink* g, T v){  int p = getVertexIndex(g, v);  if(p == -1)return;  //删除目标顶点以外的顶点,与目标顶点之间的边
  for(int i = 0; i < g->NumVertices; ++i){    if(i == p){      continue;
    }else{
      remove_edge_(&(g->nodeTable[i].adj), p);
    }
  }  //删除目标顶点行的所有边
  Edge* te = g->nodeTable[p].adj;
  Edge* tmp;  while(te != NULL){
    tmp = te;
    te = te->link;    free(tmp);
  }  //让被删除顶点那行,指向最后一个顶点那行。
  //因为最后一行向上移动了,所以要修改和最后一行有连线的点那行的线的下标。
  g->nodeTable[p].data = g->nodeTable[g->NumVertices - 1].data;
  g->nodeTable[p].adj = g->nodeTable[g->NumVertices - 1].adj;
  tmp = g->nodeTable[p].adj;
  Edge* q;  while(tmp != NULL){
    q = g->nodeTable[tmp->idx].adj;    while(q != NULL && q->idx != g->NumVertices - 1){
      q = q->link;
    }
    q->idx = p;

    tmp = tmp->link;
  }
  g->NumVertices--;
}//销毁图void destroy_graph_link(GraphLink* g){  //释放所有边的内存空间
  Edge* t = NULL;
  Edge* p = NULL;  for(int i = 0; i< g->NumVertices; ++i){
    t = g->nodeTable[i].adj;    while(NULL != t){
      p = t;
      t = t->link;      free(p);
    }
  }  //释放所有顶点的内存空间
  free(g->nodeTable);
  g->nodeTable = NULL;
  g->MaxVertices = g->NumVertices = g->NumEdges = 0;
}//取得指定顶点的第一个后序顶点int get_first_neighbor(GraphLink* g, T v){  int i = getVertexIndex(g, v);  if (-1 == i)return -1;
  Edge* p = g->nodeTable[i].adj;  if(NULL != p)    return p->idx;  else
    return -1;
}//取得指定顶点v1的临街顶点v2的第一个后序顶点int get_next_neighbor(GraphLink* g, T ve1, T ve2){  int v1 = getVertexIndex(g, ve1);  int v2 = getVertexIndex(g, ve2);  if(v1 == -1 || v2 == -1)return -1;

  Edge* t = g->nodeTable[v1].adj;  while(t != NULL && t->idx != v2){
    t = t->link;
  }  if(NULL != t && t->link != NULL){    return t->link->idx;
  }  return -1;
}

graph_linkmain.c

#include "graph_link.h"int main(){
  GraphLink gl;  //初始化图
  init_graph_link(&gl);  //插入节点
  insert_vertex(&gl, 'A');
  insert_vertex(&gl, 'B');
  insert_vertex(&gl, 'C');
  insert_vertex(&gl, 'D');
  insert_vertex(&gl, 'E');  //显示图
  //show_graph_link(&gl);

  //插入边(尾插)
  /*
  insert_edge_tail(&gl, 'A', 'B');
  insert_edge_tail(&gl, 'A', 'D');
  insert_edge_tail(&gl, 'B', 'C');
  insert_edge_tail(&gl, 'B', 'E');
  insert_edge_tail(&gl, 'C', 'D');
  insert_edge_tail(&gl, 'C', 'E');
  */

  //插入边(头插)
  ///*
  insert_edge_head(&gl, 'A', 'B');
  insert_edge_head(&gl, 'A', 'D');
  insert_edge_head(&gl, 'B', 'C');
  insert_edge_head(&gl, 'B', 'E');
  insert_edge_head(&gl, 'C', 'D');
  insert_edge_head(&gl, 'C', 'E');  //*/
  //显示图
  show_graph_link(&gl);  printf("\n");  //删除边
  remove_edge(&gl, 'A', 'D');  //显示图
  show_graph_link(&gl);  printf("\n");  //删除顶点
  remove_vertex(&gl, 'C');  //显示图
  show_graph_link(&gl);  //临街顶点的下标
  int v = get_first_neighbor(&gl, 'B');  
  printf("%d\n", v);
  v = get_next_neighbor(&gl, 'B', 'A');  
  printf("%d\n", v);  //销毁图
  destroy_graph_link(&gl);
}

作者:小石王

原文链接:https://www.cnblogs.com/xiaoshiwang/p/9394347.html

0人推荐
随时随地看视频
慕课网APP