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