Cデータ構造とアルゴリズム - 連結の基礎 - 図02:グラフを作成するには、2つの最も一般的な方法

主要讲解图的最常用的两种创建方式,邻接矩阵和邻接表,代码实现

0x01で。隣接行列

意味:二つの配列情報またはアークエッジを格納する頂点の一次元配列に格納された情報、二次元配列(隣接行列)を示す図。

通常のビューのための(図なしの重みを参照)。

あなたの場合(V_ {I}、V_ {J})\とEまたは  <V_ {I}、V)_ {J}> \ Eでそれから  【J \右] = 1左\ [I \右】左\アーク

逆に、[J \右] = 0、左\ [I \右]左\アーク

度頂点を求め、実際には、この頂点  V_ {I}のマトリクスにおける  私行の要素と。

次のような無向グラフについて

図については、のような:

図ネットは、重み付けされた値は、図です。

あなたの場合  (V_ {I}、V_ {J})\とEや  <V_ {I}、V)_ {J}> \ Eで、その後  左\ [I \右]左[J \右] = W_ {IJ} \アーク(Wは重量を参照します)。

もし  I = J、その後、  [J \右] = 0、左\ [I \右]左\アーク

エッジ点が存在しない場合、それはし  \ propto、一般に、従来の値によって達成することが不可能と考えられ、32727,65535として表さ。以下のような:

構造:

#define MAXSIZE 100
#define INTMAX 32767//通常认为无法到达的int值,short型的边界值
typedef struct
{
	char ver[MAXSIZE];//顶点信息域
	int edge[MAXSIZE][MAXSIZE];
	int numv;//顶点数
	int nume;//边数
}Graph;

初出:

void CreateGraph(Graph *G)
{
	int i, j, k, w;
	printf("请输入图的顶点数和边数:\n");
	scanf("%d %d", &G->numv, &G->nume);
	while (getchar() != '\n');
	printf("请输入节点信息:");
	for (i = 0; i < G->numv; i++)//读入顶点信息
	{
		scanf("%c", &G->ver[i]);
	}
	for (i = 0; i < G->numv; i++)//初始化邻接矩阵
	{
		for (j = 0; j < G->numv; j++)
		{
			G->edge[i][j] = INTMAX;
		}
	}
	for (k = 0; k < G->nume; k++)//读入边信息,最好加上i-i权值为0,不然其它都会是INTMAX
	{
		printf("请输入第  %d  条边(Vi,Vj)的下标i,j,和权值w:\n", k + 1);
		while (getchar() != '\n');//必须清空缓冲区
		scanf("%d %d %d",&i, &j, &w);
		G->edge[i][j] = w;
		G->edge[j][i] = G->edge[i][j];//无向图则矩阵对称,有向图不需要
	}
}

時間の複雑さ:N Eの頂点のエッジが作成O(N + N ^ {2} + E)、初期化、 O(N ^ {2})

0×02。隣接リスト

:意味グラフの隣接行列内のエッジの数が少ない無駄であるため、その後、チェーンメモリ構造に格納されたサイド情報を使用することを検討して、頂点を格納する一次元アレイ、アレイは、第1のエッジを示すポインタを格納し、エッジリスト単一のチェーン店、例えば頂点と辺はアップ接続します。

欠陥は:隣接テーブルが格納されている、すなわち、頂点、頂点のデフォルトであり、レベル情報を決定することは困難です。

逆隣接テーブル:欠陥情報の隣接リストを解くことを求めることはできないが、隣接テーブル頂点最初のアークを確立するために、しかし度情報を判別できません。

アイコン:

 

構造:

#define MAXSIZE 100


//边表结构
typedef struct EdgeNode
{
	int adjvex;//存储该顶点对应的数组下标
	int weight;//存储权值
	struct EdgeNode* next;//指针域,指向下一个邻接点
}EdgeNode;

//顶点结构
typedef struct VertexNode
{
	char data;//存储顶点的信息
	EdgeNode* firstedge;//代表边表的头指针
}VertexNode,AdjList[MAXSIZE];//同时创建了一个大小为MAXSIZE的顶点数组

//整个图结构
typedef struct
{
	AdjList adjList;//此时的AdjList代表顶点表的指针类型,adjList就是创建的顶点表数组
	int numv;//顶点数
	int nume;//边数
}GraphAdjList;

初出:

void CreateALGraph(GraphAdjList* G)
{
	int i, j,k,w;
	EdgeNode* e;//建立边表的头结点
	printf("请输入顶点数目和边数目,以空格隔开\n");
	scanf("%d %d", &G->numv, &G->nume);
        while (getchar() != '\n');//必须清空缓冲区
	for (i = 0; i < G->numv; i++)//开始建立顶点表
	{
		scanf("%c", &G->adjList[i].data);//读取数据域
		G->adjList[i].firstedge = NULL;//初始化边表头指针
	}
	for (k = 0; k < G->nume; k++)//开始建立边表
	{
		printf("请输入边左端下标 i ,右端下标 j,和权值 :\n");
                while (getchar() != '\n');//必须清空缓冲区
		scanf("%d %d %d", &i,&j,&w);
		e = (EdgeNode*)malloc(sizeof(EdgeNode));//边表头结点申请内存
		e->adjvex = j;//存储 i 指向的顶点的下标
		e->weight = w;//存储该边的权值
		e->next = G->adjList[i].firstedge;//将 e 指向顶点表中的边表头结点
		G->adjList[i].firstedge = e;//将当前顶点表的头节点指向e,单链表的头插法
		//以下代码对于无向图而言,对称的
		e = (EdgeNode*)malloc(sizeof(EdgeNode));//e重新申请一块内存
		e->adjvex = i;
		e->weight = w;
		e->next = G->adjList[j].firstedge;
		G->adjList[j].firstedge = e;
	}
}

共通トラバーサルの隣接リスト:

void PrintfGraphAdjList(GraphAdjList G)//只传结构,不传指针,以防遍历时改变原来结构
{
	for (int i = 0; i < G.numv; i++)
	{
		EdgeNode* p = G.adjList[i].firstedge;
		printf("顶点 %c  的边有:\n", G.adjList[i].data);
		while (p)//遍历链表
		{
			printf("顶点  %c  到顶点  %c  ,权值为  %d  \n", G.adjList[i].data, G.adjList[p->adjvex].data, p->weight);
			p = p->next;
		}
		printf("\n");
	}
}

時間計算:n個の頂点エッジE O(N + E)

主な機能テスト:

int main()
{
	GraphAdjList G;
	CreateALGraph(&G);
	PrintfGraphAdjList(G);
	return 0;
}

 

 

 

この章では、終了します。

 

公開された19元の記事 ウォン称賛7 ビュー409

おすすめ

転載: blog.csdn.net/ATFWUS/article/details/104324417