• 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);
    }
    
    
  • 相关阅读:
    The Joy of Clojure – Laziness(6.3)
    Python Decorator Closure
    Programming clojure – Recursion and Lazyseq
    Programming Clojure Unifying Data with Sequences
    SharePoint Workflow的code运行在哪个进程? w3wp.exe 还是OWSTimer.exe?
    利用PsExec提升命令行的安全级别, 绕过组策略执行命令
    WinDBG脚本入门
    记录一个SPS2010中RSS Web Part报错的问题
    User的Delegation选项卡在Active Directory Users and Computers找不到?
    修改SPS2010的Search Core Results webpart, 令其显示文档被索引了的所有属性
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/9394347.html
Copyright © 2020-2023  润新知