第41棵 - 图的存储结构

1. 邻接矩阵法

用一维数组存储顶点--描述顶点相关的数据。

用二维数组存储边--描述顶点的边。

设图A = (V,E)是一个有n个顶点的图,图的邻接矩阵为Edge[n][n],则:Edge[i][j] = W,W>0,i和j连接;Edge[i][j] = 0,i == j 或者i和j不链接。

注:W为权值,当需要权值时,取W为1表示结点间连接。

无向图的邻接矩阵是对称的。

有向图的邻接矩阵可能是不对称的。

2. 邻接矩阵法的头结点

记录定点的个数。

记录与顶点相关的数据描述。

记录描述边集的二维数组。

typedef struct _tag_MGraph

{

int count;

MVertex** v;

int** matrix;

}TMGraph;

问题:如何根据顶点数目,动态创建二维数组?

3. 动态申请二维数组的原理

通过二级指针动态申请一位数组。

通过一级指针申请数据空间。

将一维指针数组中的指针连接到数据空间。

int** malloc2d(int row, int col)

{

int** ret = (int**)malloc(sizeof(int*) * row);

int* p = (int*)malloc(sizeof(int) * row *col);

int i = 0;

if(p && ret)

{

for(i=0;i<row;i++)

{

ret[i] = p + i * col;

}

}

else

{

free(ret);

fre(p);

ret = NULL;

}

return ret;

}

4. 程序——邻接矩阵法实现图结构

main.c

#include <stdio.h>

#include <stdlib.h>

#include "LGraph.h"

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

void print_data(LVertex* v)

{

printf("%s", (char*)v);

}

int main(int argc, char *argv[])

{

LVertex* v[] = {"A", "B", "C", "D", "E", "F"};

LGraph* graph = LGraph_Create(v, 6);

LGraph_AddEdge(graph, 0, 1, 1);

LGraph_AddEdge(graph, 0, 2, 1);

LGraph_AddEdge(graph, 0, 3, 1);

LGraph_AddEdge(graph, 1, 5, 1);

LGraph_AddEdge(graph, 1, 4, 1);

LGraph_AddEdge(graph, 2, 1, 1);

LGraph_AddEdge(graph, 3, 4, 1);

LGraph_AddEdge(graph, 4, 2, 1);

LGraph_Display(graph, print_data);

LGraph_DFS(graph, 0, print_data);

LGraph_BFS(graph, 0, print_data);

LGraph_Destroy(graph);

return 0;

}

LGraph.h

#ifndef _LGRAPH_H_

#define _LGRAPH_H_

typedef void LGraph;

typedef void LVertex;

typedef void (LGraph_Printf)(LVertex*);

LGraph* LGraph_Create(LVertex** v, int n);

void LGraph_Destroy(LGraph* graph);

void LGraph_Clear(LGraph* graph);

int LGraph_AddEdge(LGraph* graph, int v1, int v2, int w);

int LGraph_RemoveEdge(LGraph* graph, int v1, int v2);

int LGraph_GetEdge(LGraph* graph, int v1, int v2);

int LGraph_TD(LGraph* graph, int v);

int LGraph_VertexCount(LGraph* graph);

int LGraph_EdgeCount(LGraph* graph);

void LGraph_DFS(LGraph* graph, int v, LGraph_Printf* pFunc);

void LGraph_BFS(LGraph* graph, int v, LGraph_Printf* pFunc);

void LGraph_Display(LGraph* graph, LGraph_Printf* pFunc);

#endif

LGraph.c

#include <malloc.h>

#include <stdio.h>

#include "LGraph.h"

#include "LinkList.h"

#include "LinkQueue.h"

typedef struct _tag_LGraph

{

int count;

LVertex** v;

LinkList** la;

} TLGraph;

typedef struct _tag_ListNode

{

LinkListNode header;

int v;

int w;

} TListNode;

static void recursive_dfs(TLGraph* graph, int v, int visited[], LGraph_Printf* pFunc)

{

int i = 0;

pFunc(graph->v[v]);

visited[v] = 1;

printf(", ");

for(i=0; i<LinkList_Length(graph->la[v]); i++)

{

TListNode* node = (TListNode*)LinkList_Get(graph->la[v], i);

if( !visited[node->v] )

{

recursive_dfs(graph, node->v, visited, pFunc);

}

}

}

static void bfs(TLGraph* graph, int v, int visited[], LGraph_Printf* pFunc)

{

LinkQueue* queue = LinkQueue_Create();

if( queue != NULL )

{

LinkQueue_Append(queue, graph->v + v);

visited[v] = 1;

while( LinkQueue_Length(queue) > 0 )

{

int i = 0;

v = (LVertex**)LinkQueue_Retrieve(queue) - graph->v;

pFunc(graph->v[v]);

printf(", ");

for(i=0; i<LinkList_Length(graph->la[v]); i++)

{

TListNode* node = (TListNode*)LinkList_Get(graph->la[v], i);

if( !visited[node->v] )

{

LinkQueue_Append(queue, graph->v + node->v);

visited[node->v] = 1;

}

}

}

}

LinkQueue_Destroy(queue);

}

LGraph* LGraph_Create(LVertex** v, int n)  // O(n)

{

TLGraph* ret = NULL;

int ok = 1;

if( (v != NULL ) && (n > 0) )

{

ret = (TLGraph*)malloc(sizeof(TLGraph));

if( ret != NULL )

{

ret->count = n;

ret->v = (LVertex**)calloc(n, sizeof(LVertex*));

ret->la = (LinkList**)calloc(n, sizeof(LinkList*));

ok = (ret->v != NULL) && (ret->la != NULL);

if( ok )

{

int i = 0;

for(i=0; i<n; i++)

{

ret->v[i] = v[i];

}

for(i=0; (i<n) && ok; i++)

{

ok = ok && ((ret->la[i] = LinkList_Create()) != NULL);

}

}

if( !ok )

{

if( ret->la != NULL )

{

int i = 0;

for(i=0; i<n; i++)

{

LinkList_Destroy(ret->la[i]);

}

}

free(ret->la);

free(ret->v);

free(ret);

ret = NULL;

}

}

}

return ret;

}

void LGraph_Destroy(LGraph* graph) // O(n*n)

{

TLGraph* tGraph = (TLGraph*)graph;

LGraph_Clear(tGraph);

if( tGraph != NULL )

{

int i = 0;

for(i=0; i<tGraph->count; i++)

{

LinkList_Destroy(tGraph->la[i]);

}

free(tGraph->la);

free(tGraph->v);

free(tGraph);

}

}

void LGraph_Clear(LGraph* graph) // O(n*n)

{

TLGraph* tGraph = (TLGraph*)graph;

if( tGraph != NULL )

{

int i = 0;

for(i=0; i<tGraph->count; i++)

{

while( LinkList_Length(tGraph->la[i]) > 0 )

{

free(LinkList_Delete(tGraph->la[i], 0));

}

}

}

}

int LGraph_AddEdge(LGraph* graph, int v1, int v2, int w) // O(1)

{

TLGraph* tGraph = (TLGraph*)graph;

TListNode* node = NULL;

int ret = (tGraph != NULL);

ret = ret && (0 <= v1) && (v1 < tGraph->count);

ret = ret && (0 <= v2) && (v2 < tGraph->count);

ret = ret && (0 < w) && ((node = (TListNode*)malloc(sizeof(TListNode))) != NULL);

if( ret )

{

node->v = v2;

node->w = w;

LinkList_Insert(tGraph->la[v1], (LinkListNode*)node, 0);

}

return ret;

}

int LGraph_RemoveEdge(LGraph* graph, int v1, int v2) // O(n*n)

{

TLGraph* tGraph = (TLGraph*)graph;

int condition = (tGraph != NULL);

int ret = 0;

condition = condition && (0 <= v1) && (v1 < tGraph->count);

condition = condition && (0 <= v2) && (v2 < tGraph->count);

if( condition )

{

TListNode* node = NULL;

int i = 0;

for(i=0; i<LinkList_Length(tGraph->la[v1]); i++)

{

node = (TListNode*)LinkList_Get(tGraph->la[v1], i);

if( node->v == v2)

{

ret = node->w;

LinkList_Delete(tGraph->la[v1], i);

free(node);

break;

}

}

}

return ret;

}

int LGraph_GetEdge(LGraph* graph, int v1, int v2) // O(n*n)

{

TLGraph* tGraph = (TLGraph*)graph;

int condition = (tGraph != NULL);

int ret = 0;

condition = condition && (0 <= v1) && (v1 < tGraph->count);

condition = condition && (0 <= v2) && (v2 < tGraph->count);

if( condition )

{

TListNode* node = NULL;

int i = 0;

for(i=0; i<LinkList_Length(tGraph->la[v1]); i++)

{

node = (TListNode*)LinkList_Get(tGraph->la[v1], i);

if( node->v == v2)

{

ret = node->w;

break;

}

}

}

return ret;

}

int LGraph_TD(LGraph* graph, int v) // O(n*n*n)

{

TLGraph* tGraph = (TLGraph*)graph;

int condition = (tGraph != NULL);

int ret = 0;

condition = condition && (0 <= v) && (v < tGraph->count);

if( condition )

{

int i = 0;

int j = 0;

for(i=0; i<tGraph->count; i++)

{

for(j=0; j<LinkList_Length(tGraph->la[i]); j++)

{

TListNode* node = (TListNode*)LinkList_Get(tGraph->la[i], j);

if( node->v == v )

{

ret++;

}

}

}

ret += LinkList_Length(tGraph->la[v]);

}

return ret;

}

int LGraph_VertexCount(LGraph* graph) // O(1)

{

TLGraph* tGraph = (TLGraph*)graph;

int ret = 0;

if( tGraph != NULL )

{

ret = tGraph->count;

}

return ret;

}

int LGraph_EdgeCount(LGraph* graph) // O(n)

{

TLGraph* tGraph = (TLGraph*)graph;

int ret = 0;

if( tGraph != NULL )

{

int i = 0;

for(i=0; i<tGraph->count; i++)

{

ret += LinkList_Length(tGraph->la[i]);

}

}

return ret;

}

void LGraph_DFS(LGraph* graph, int v, LGraph_Printf* pFunc)

{

TLGraph* tGraph = (TLGraph*)graph;

int* visited = NULL;

int condition = (tGraph != NULL);

condition = condition && (0 <= v) && (v < tGraph->count);

condition = condition && (pFunc != NULL);

condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL);

if( condition )

{

int i = 0;

recursive_dfs(tGraph, v, visited, pFunc);

for(i=0; i<tGraph->count; i++)

{

if( !visited[i] )

{

recursive_dfs(tGraph, i, visited, pFunc);

}

}

printf("\n");

}

free(visited);

}

void LGraph_BFS(LGraph* graph, int v, LGraph_Printf* pFunc)

{

TLGraph* tGraph = (TLGraph*)graph;

int* visited = NULL;

int condition = (tGraph != NULL);

condition = condition && (0 <= v) && (v < tGraph->count);

condition = condition && (pFunc != NULL);

condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL);

if( condition )

{

int i = 0;

bfs(tGraph, v, visited, pFunc);

for(i=0; i<tGraph->count; i++)

{

if( !visited[i] )

{

bfs(tGraph, i, visited, pFunc);

}

}

printf("\n");

}

free(visited);

}

void LGraph_Display(LGraph* graph, LGraph_Printf* pFunc) // O(n*n*n)

{

TLGraph* tGraph = (TLGraph*)graph;

if( (tGraph != NULL) && (pFunc != NULL) )

{

int i = 0;

int j = 0;

for(i=0; i<tGraph->count; i++)

{

printf("%d:", i);

pFunc(tGraph->v[i]);

printf(" ");

}

printf("\n");

for(i=0; i<tGraph->count; i++)

{

for(j=0; j<LinkList_Length(tGraph->la[i]); j++)

{

TListNode* node = (TListNode*)LinkList_Get(tGraph->la[i], j);

printf("<");

pFunc(tGraph->v[i]);

printf(", ");

pFunc(tGraph->v[node->v]);

printf(", %d", node->w);

printf(">");

printf(" ");

}

}

printf("\n");

}

}

LinkList.h

LinkList.c

LinkQueue.h

LinkQueue.c

5. 邻接表示法

从一个顶点出发的边连接在同一个链表中。

每一个链表结点代表一条边,结点中保存边的另一个顶点的下标和权值。

6. 邻接链表发的头结点

记录定点个数。

记录与顶点相关的数据描述。

记录描述边集的链表数组。

typedef struct _tag_LGraph

{

int count;

LVertex** v;

LinkList** la;

}TLGraph;

7. 程序——邻接链表发实现图结构

main.c

#include <stdio.h>

#include <stdlib.h>

#include "MGraph.h"

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

void print_data(MVertex* v)

{

printf("%s", (char*)v);

}

int main(int argc, char *argv[])

{

MVertex* v[] = {"A", "B", "C", "D", "E", "F"};

MGraph* graph = MGraph_Create(v, 6);

MGraph_AddEdge(graph, 0, 1, 1);

MGraph_AddEdge(graph, 0, 2, 1);

MGraph_AddEdge(graph, 0, 3, 1);

MGraph_AddEdge(graph, 1, 5, 1);

MGraph_AddEdge(graph, 1, 4, 1);

MGraph_AddEdge(graph, 2, 1, 1);

MGraph_AddEdge(graph, 3, 4, 1);

MGraph_AddEdge(graph, 4, 2, 1);

MGraph_Display(graph, print_data);

MGraph_DFS(graph, 0, print_data);

MGraph_BFS(graph, 0, print_data);

MGraph_Destroy(graph);

return 0;

}

MGraph.h

#ifndef _MGRAPH_H_

#define _MGRAPH_H_

typedef void MGraph;

typedef void MVertex;

typedef void (MGraph_Printf)(MVertex*);

MGraph* MGraph_Create(MVertex** v, int n);

void MGraph_Destroy(MGraph* graph);

void MGraph_Clear(MGraph* graph);

int MGraph_AddEdge(MGraph* graph, int v1, int v2, int w);

int MGraph_RemoveEdge(MGraph* graph, int v1, int v2);

int MGraph_GetEdge(MGraph* graph, int v1, int v2);

int MGraph_TD(MGraph* graph, int v);

int MGraph_VertexCount(MGraph* graph);

int MGraph_EdgeCount(MGraph* graph);

void MGraph_DFS(MGraph* graph, int v, MGraph_Printf* pFunc);

void MGraph_BFS(MGraph* graph, int v, MGraph_Printf* pFunc);

void MGraph_Display(MGraph* graph, MGraph_Printf* pFunc);

#endif

MGraph.c

#include <malloc.h>

#include <stdio.h>

#include "MGraph.h"

#include "LinkQueue.h"

typedef struct _tag_MGraph

{

int count;

MVertex** v;

int** matrix;

} TMGraph;

static void recursive_dfs(TMGraph* graph, int v, int visited[], MGraph_Printf* pFunc)

{

int i = 0;

pFunc(graph->v[v]);

visited[v] = 1;

printf(", ");

for(i=0; i<graph->count; i++)

{

if( (graph->matrix[v][i] != 0) && !visited[i] )

{

recursive_dfs(graph, i, visited, pFunc);

}

}

}

static void bfs(TMGraph* graph, int v, int visited[], MGraph_Printf* pFunc)

{

LinkQueue* queue = LinkQueue_Create();

if( queue != NULL )

{

LinkQueue_Append(queue, graph->v + v);

visited[v] = 1;

while( LinkQueue_Length(queue) > 0 )

{

int i = 0;

v = (MVertex**)LinkQueue_Retrieve(queue) - graph->v;

pFunc(graph->v[v]);

printf(", ");

for(i=0; i<graph->count; i++)

{

if( (graph->matrix[v][i] != 0) && !visited[i] )

{

LinkQueue_Append(queue, graph->v + i);

visited[i] = 1;

}

}

}

}

LinkQueue_Destroy(queue);

}

MGraph* MGraph_Create(MVertex** v, int n)  // O(n)

{

TMGraph* ret = NULL;

if( (v != NULL ) && (n > 0) )

{

ret = (TMGraph*)malloc(sizeof(TMGraph));

if( ret != NULL )

{

int* p = NULL;

ret->count = n;

ret->v = (MVertex**)malloc(sizeof(MVertex*) * n);

ret->matrix = (int**)malloc(sizeof(int*) * n);

p = (int*)calloc(n * n, sizeof(int));

if( (ret->v != NULL) && (ret->matrix != NULL) && (p != NULL) )

{

int i = 0;

for(i=0; i<n; i++)

{

ret->v[i] = v[i];

ret->matrix[i] = p + i * n;

}

}

else

{

free(p);

free(ret->matrix);

free(ret->v);

free(ret);

ret = NULL;

}

}

}

return ret;

}

void MGraph_Destroy(MGraph* graph) // O(1)

{

TMGraph* tGraph = (TMGraph*)graph;

if( tGraph != NULL )

{

free(tGraph->v);

free(tGraph->matrix[0]);

free(tGraph->matrix);

free(tGraph);

}

}

void MGraph_Clear(MGraph* graph) // O(n*n)

{

TMGraph* tGraph = (TMGraph*)graph;

if( tGraph != NULL )

{

int i = 0;

int j = 0;

for(i=0; i<tGraph->count; i++)

{

for(j=0; j<tGraph->count; j++)

{

tGraph->matrix[i][j] = 0;

}

}

}

}

int MGraph_AddEdge(MGraph* graph, int v1, int v2, int w) // O(1)

{

TMGraph* tGraph = (TMGraph*)graph;

int ret = (tGraph != NULL);

ret = ret && (0 <= v1) && (v1 < tGraph->count);

ret = ret && (0 <= v2) && (v2 < tGraph->count);

ret = ret && (0 <= w);

if( ret )

{

tGraph->matrix[v1][v2] = w;

}

return ret;

}

int MGraph_RemoveEdge(MGraph* graph, int v1, int v2) // O(1)

{

int ret = MGraph_GetEdge(graph, v1, v2);

if( ret != 0 )

{

((TMGraph*)graph)->matrix[v1][v2] = 0;

}

return ret;

}

int MGraph_GetEdge(MGraph* graph, int v1, int v2) // O(1)

{

TMGraph* tGraph = (TMGraph*)graph;

int condition = (tGraph != NULL);

int ret = 0;

condition = condition && (0 <= v1) && (v1 < tGraph->count);

condition = condition && (0 <= v2) && (v2 < tGraph->count);

if( condition )

{

ret = tGraph->matrix[v1][v2];

}

return ret;

}

int MGraph_TD(MGraph* graph, int v) // O(n)

{

TMGraph* tGraph = (TMGraph*)graph;

int condition = (tGraph != NULL);

int ret = 0;

condition = condition && (0 <= v) && (v < tGraph->count);

if( condition )

{

int i = 0;

for(i=0; i<tGraph->count; i++)

{

if( tGraph->matrix[v][i] != 0 )

{

ret++;

}

if( tGraph->matrix[i][v] != 0 )

{

ret++;

}

}

}

return ret;

}

int MGraph_VertexCount(MGraph* graph) // O(1)

{

TMGraph* tGraph = (TMGraph*)graph;

int ret = 0;

if( tGraph != NULL )

{

ret = tGraph->count;

}

return ret;

}

int MGraph_EdgeCount(MGraph* graph) // O(n*n)

{

TMGraph* tGraph = (TMGraph*)graph;

int ret = 0;

if( tGraph != NULL )

{

int i = 0;

int j = 0;

for(i=0; i<tGraph->count; i++)

{

for(j=0; j<tGraph->count; j++)

{

if( tGraph->matrix[i][j] != 0 )

{

ret++;

}

}

}

}

return ret;

}

void MGraph_DFS(MGraph* graph, int v, MGraph_Printf* pFunc)

{

TMGraph* tGraph = (TMGraph*)graph;

int* visited = NULL;

int condition = (tGraph != NULL);

condition = condition && (0 <= v) && (v < tGraph->count);

condition = condition && (pFunc != NULL);

condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL);

if( condition )

{

int i = 0;

recursive_dfs(tGraph, v, visited, pFunc);

for(i=0; i<tGraph->count; i++)

{

if( !visited[i] )

{

recursive_dfs(tGraph, i, visited, pFunc);

}

}

printf("\n");

}

free(visited);

}

void MGraph_BFS(MGraph* graph, int v, MGraph_Printf* pFunc)

{

TMGraph* tGraph = (TMGraph*)graph;

int* visited = NULL;

int condition = (tGraph != NULL);

condition = condition && (0 <= v) && (v < tGraph->count);

condition = condition && (pFunc != NULL);

condition = condition && ((visited = (int*)calloc(tGraph->count, sizeof(int))) != NULL);

if( condition )

{

int i = 0;

bfs(tGraph, v, visited, pFunc);

for(i=0; i<tGraph->count; i++)

{

if( !visited[i] )

{

bfs(tGraph, i, visited, pFunc);

}

}

printf("\n");

}

free(visited);

}

void MGraph_Display(MGraph* graph, MGraph_Printf* pFunc) // O(n*n)

{

TMGraph* tGraph = (TMGraph*)graph;

if( (tGraph != NULL) && (pFunc != NULL) )

{

int i = 0;

int j = 0;

for(i=0; i<tGraph->count; i++)

{

printf("%d:", i);

pFunc(tGraph->v[i]);

printf(" ");

}

printf("\n");

for(i=0; i<tGraph->count; i++)

{

for(j=0; j<tGraph->count; j++)

{

if( tGraph->matrix[i][j] != 0 )

{

printf("<");

pFunc(tGraph->v[i]);

printf(", ");

pFunc(tGraph->v[j]);

printf(", %d", tGraph->matrix[i][j]);

printf(">");

printf(" ");

}

}

}

printf("\n");

}

}

LinkQueue.h

LinkQueue.c

小结:

邻接矩阵法

邻接链表法

优点:直观,容易实现。

缺点:当顶点数较多,而边数较少是浪费时间和空间。

优点:有效利用空间,非常适合边数较少的图。

缺点:实现相对复杂,不容易查找两个顶点之间的权值。

邻接矩阵法和邻接链表法的选择不是绝对的,需要根据实际情况综合考虑。

转载于:https://www.cnblogs.com/free-1122/p/11336068.html

数据--第41棵 - 图的存储结构相关推荐

  1. 数据结构之图的存储结构:邻接多重表

    图的存储结构:邻接多重表 产生条件: 邻接多重表的定义: 邻接多重表的代码定义: 删除: 性能分析: 十字链表与邻接多重表的对比 产生条件: 当用邻接矩阵法存储时:空间复杂度为O(|V|^2),太大 ...

  2. 数据结构之图的存储结构:十字链表法

    图的存储结构:十字链表法 思维导图: 产生条件: 十字链表法的定义: 十字链表法的代码定义: 性能分析: 思维导图: 产生条件: 当用邻接矩阵存储时:空间复杂度为O(|v|^2),太大 当用邻接表法存 ...

  3. 数据结构之图的存储结构:邻接表法

    图的存储结构:邻接表法 产生条件: 邻接表法的定义: 邻接表法的特点: 邻接表法的代码定义: 邻接表法与邻接矩阵法的对比: 产生条件: 当用邻接矩阵存储时:空间复杂度为O(|v|^2),太大 邻接表法 ...

  4. 数据结构之图的存储结构一及其实现

    图的存储结构 由于图的结构比较复杂,任意两个顶点之间都可能存在联系,因此无法以数据元素在存储区中的物理位置来表示元素之间的关系,即图没有顺序映像的存储结构,但可以借助数组的数据类型表示元素之间的关系. ...

  5. 数据结构——图(存储结构)

    数据结构--图 图的定义和基本术语 图的类型定义 图的存储结构 数组(邻接矩阵表示法) 网(即有权图)的邻接矩阵表示法 邻接表 邻接表表示法(链式) 图的邻接表存储表示 采用邻接表表示法创建无向网 邻 ...

  6. 图的存储结构——邻接表法

    图的存储结构--邻接表法 一.邻接表 ​ 由顶点表和边表构成,顶点表由顶点域(data)和指向第一条邻接边的指针(firstarc)构成,边表(邻接表)结点由邻接点域(adjvex)和指向下一条邻接边 ...

  7. 【数据结构——图和图的存储结构】

    目录 一.图的定义和基本术语(Graph) (一)图的定义 (二)图的基本术语 一.图的存储结构 (一)邻接矩阵(Adjacency Matrix) 1.无向图的邻接矩阵 2.有向图的邻接矩阵 3.网 ...

  8. 数据结构考研笔记(十五)——图的存储结构邻接矩阵、邻接表、十字链表、临界多重表的概念

    图的存储结构 1.邻接矩阵 1.1有向图 1.2无向图 2.邻接表法 2.1有向图边表 2.2无向图边表 3.十字链表 4.临界多重表 十字链表与临界多重表 1.邻接矩阵 邻接矩阵法结点数为n的图G ...

  9. 图的存储结构(邻接矩阵和邻接表)

    图的存储结构(邻接矩阵和邻接表) 前言: 前面我们学习图的有些定义和术语,对图这个数据结构有了新的见解和认知,让我们理解图结构的知识,今天我们学习图的存储结构,图的存储结构比较多,我们今天主要是学习邻 ...

  10. 图——图的存储结构(邻接矩阵和邻接表法)

    图的五种存储结构: 1.图的邻接矩阵表示法 图是由顶点和边或弧两部分组成.图的邻接矩阵(Adjacency Matrix)存储方式是用两个数组表示图,一个一维数组存储图中的顶点信息,一个二维数组(邻接 ...

最新文章

  1. 降低预测过程计算成本,这些NLP模型压缩方法要知道
  2. 9月份准备备考RHCE 10份考试争取一次通过
  3. Linux distributions —— 可安全安装套件,Linux发布商套件
  4. WP8.1 Study18:动态磁贴
  5. Java基本语法——(用于日后复习)
  6. 区分Activity的四种加载模式
  7. Java学习小程序(4)数列求和
  8. 网站中公用头部与尾部
  9. C#自定义控件:WinForm将其它应用程序窗体嵌入自己内部
  10. MongoDB 基础相关(二) 常用语句
  11. 图:乐清市首届民工艺术节闭幕式暨才艺表演决赛圆满结束_渤锐软件提供了【评委打分公开展示】技术支持
  12. SCT9320STDR,3.8V-32V输入,2A,低EMI,超低功耗同步降压DCDC转换器
  13. 简便word批量打印 - Office批量打印精灵(支持正版)
  14. matlab中带脚咪头怎么找,咪头用万能表怎么测_咪头怎么辨认正负极
  15. html5读取umd,UMD、CommonJS、ES Module、AMD、CMD模块的写法
  16. 多商家父订单子订单_70多份订单被退回,商家查看信息傻眼了,美团:封店180天...
  17. Premiere使用教程(五)视频导出及添加视频、音频过渡
  18. 孩子数学成绩不好怎么办_三年级发现孩子数学成绩非常不好,作为家长该怎么办?...
  19. CPU温度过高会导致电脑死机么
  20. 如何使两个家用路由器进行连接?(心得)

热门文章

  1. 进程间通信-----管道
  2. activity+window+view简单说明
  3. Java基础---基础加强---增强for循环、自动拆装箱及享元、枚举的作用、实现带有构造方法、透彻分析反射的基础_Class类、成员变量的反射、数组参数的成员方法进行反射、数组的反射应用
  4. 惠普战66一代拆机_或许这就是匠人吧 全新惠普战66二代的另类拆解
  5. java案例代码11-学生类的录入,查询,对象的封装
  6. window 2008r2 无法访问 Ox80004005
  7. html调用rpst 源码_parseHTML 函数源码解析(四) AST 基本形成
  8. 驱动程序和应用程序的区别_复仇者黑客组织—教你写第一个Linux设备驱动程序...
  9. vue string转date_进阶高级前端,这9种Vue技术你掌握了吗?
  10. Arts 第九周(5/13 ~ 5/19)