zoukankan      html  css  js  c++  java
  • 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
    ");
      }
    }
    
    //插入顶点
    void insert_vertex(GraphLink* g, T v){
      if(g->NumVertices >= g->MaxVertices)return;
      g->nodeTable[g->NumVertices++].data = v;
    }
    
    //查找顶点的index
    int 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("
    ");
    
      //删除边
      remove_edge(&gl, 'A', 'D');
      //显示图
      show_graph_link(&gl);
    
      printf("
    ");
    
      //删除顶点
      remove_vertex(&gl, 'C');
      //显示图
      show_graph_link(&gl);
    
      //临街顶点的下标
      int v = get_first_neighbor(&gl, 'B');
      printf("%d
    ", v);
      v = get_next_neighbor(&gl, 'B', 'A');
      printf("%d
    ", v);
      //销毁图
      destroy_graph_link(&gl);
    }
    
    
  • 相关阅读:
    Java实现 蓝桥杯 算法训练 画图(暴力)
    Java实现 蓝桥杯 算法训练 画图(暴力)
    Java实现 蓝桥杯 算法训练 相邻数对(暴力)
    Java实现 蓝桥杯 算法训练 相邻数对(暴力)
    Java实现 蓝桥杯 算法训练 相邻数对(暴力)
    Java实现 蓝桥杯 算法训练 Cowboys
    Java实现 蓝桥杯 算法训练 Cowboys
    55. Jump Game
    54. Spiral Matrix
    50. Pow(x, n)
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/9394347.html
Copyright © 2011-2022 走看看