Cデータ構造及びアルゴリズム - ベースの仕上げ - 図-03-直交リスト、隣接するマルチテーブル

具体实现十字链表和邻接多重表的代码

0x01の。クロスリスト

由来:

クロスリスト:隣接テーブルが決定され、唯一の相関度に対する逆隣接テーブル情報を判断し、必要が決定すると同時に、新たな構造を導入することが必要である頂点の情報にのみ適しています。

なぜそれが直交リストと呼ばれますか?

クロスリストで最初に見た頂点構造:

データ頂点データフィールドを指す。firstin尖ったヘッドアーク(エンド頂点)の頂点と頂点の、最初のうち、頂点(アーク開始点の頂点)として各円弧の端部に第一の頂点を表します。

そして、見て、テーブル構造の側面:


tailvexの、配列表の円弧端部の円弧手段headvexアークの手段をヘッドアークここ配列の添字; headLinkは、一方の縁部から始まる同じ点taillinkが片側に同じエンドポイントに向けられ、情報とも呼ばれてもよいですワイト、体重記録面。

頂点から出発して、ポインタは、次に、特定の一つのエッジに、エッジに始点firstin選択することができ、次のエッジの同じ端部の隣に、またはポイントの同じエッジに開始点を選択することができ、複数のに各チャンネルまた、クロス、いわゆるクロスリンクリストのような。

注意:クロスリストは有向グラフに適用されます。

リンクリストを渡り:

#define MAXSIZE 100

//边表结构
typedef struct EdgeNode
{
	int tailvex;//弧起点在顶点表中的下标
	int headvex;//弧终点在顶点表中的下标
	struct EdgeNode* headlink;//指向起点相同的下一条边
	struct EdgeNode* taillink;//指向终点相同的下一条边
	int weight;//存储权值
}EdgeNode;

//顶点表结构
typedef struct VexNode
{
	char data;//顶点数据域
	EdgeNode* firstin;//以该顶点为弧终点(弧头)的边表头指针
	EdgeNode* firstout;//以该顶点为弧起点(弧尾)的边表头指针
}VexNode,VexList[MAXSIZE];//同时创建了一个顶点表数组

//十字链表图结构
typedef struct
{
	VexList vexlist;//顶点表
	int numv;//顶点数
	int nume;//边数
}OLGraph;

クロスは、リストを作成します。

void CreateOLGraph(OLGraph* G)
{
	int i, j, k, w;
	printf("请输入图的顶点数和边数:\n");
	scanf("%d %d", &G->numv, &G->nume);
	while (getchar() != '\n');//清空缓冲区
	for (i = 0; i < G->numv; i++)//录入顶点信息
	{
		scanf("%c", &G->vexlist[i].data);
		G->vexlist[i].firstin = NULL;//初始化
		G->vexlist[i].firstout = NULL;
	}
	for (k = 0; k < G->nume; k++)//录入边信息
	{
		printf("请输入弧的起点在数组中的下标,终点在数组中的下标,和权值:\n");
		while (getchar() != '\n');//清空缓冲区
		scanf("%d %d %d", &i, &j, &w);
		EdgeNode* e = (EdgeNode*)malloc(sizeof(EdgeNode));
		e->tailvex = i;
		e->headvex = j;
		e->weight=w;
		e->headlink = G->vexlist[j].firstin;//头插法
		e->taillink = G->vexlist[i].firstout;//头插法
		G->vexlist[j].firstin = e;
		G->vexlist[i].firstout = e;
	}
}

一般的なトラバーサルのクロス一覧:

void PrintOLGraph(OLGraph G)
{
	for (int i = 0; i < G.numv; i++)
	{
		EdgeNode* p = G.vexlist[i].firstin;
		printf("以顶点 %c 为头的边有:\n", G.vexlist[i].data);
		int numhead = 0;//记录入度数
		while (p)
		{
			printf("顶点 %c 到顶点 %c ,权值为 %d \n",G.vexlist[p->tailvex].data,G.vexlist[p->headvex].data,p->weight);
			numhead++;
			p = p->headlink;
		}
		printf("该顶点的入度为 %d \n", numhead);
		printf("以顶点 %c 为尾的边有:\n", G.vexlist[i].data);
		int numtail = 0;//记录出度数
		p = G.vexlist[i].firstout;
		while (p)
		{
			printf("顶点 %c 到顶点 %c ,权值为 %d \n", G.vexlist[p->tailvex].data, G.vexlist[p->headvex].data, p->weight);
			numtail++;
			p = p->taillink;
		}
		printf("该顶点的出度为 %d \n", numtail);
	}
}

0x02の隣接するマルチテーブル

由来:

私たちはより多くのマーク・ツー・エッジエッジで待っている間に、既に、削除操作を隣接リストグラフを訪問した不安がある場合は、クロスリストは、無料で、有向グラフのために最適化され、その後、我々は、隣接する複数のテーブルを使用する必要があります。

頂点テーブル構造が示さ:

隣接リストと頂点構造と同様に、データは、データ・フィールドを指し、firstedgeは有向第一の側を指します。

エッジリストは、構造を示します。

  • マーク:変数をマーカーとして、このエッジノードが訪問されているかどうかを記録します。
  • ivex:頂点配列内のインデックス記録端縁、
  • jvex:頂点索引アレイに他端側を記録します。
  • ILINK:端子Iに関連付けられた次のエッジポインター。
  • JLINK:Jの端部に関連付けられた次のエッジへのポインタ。

構造:

#define MAXSIZE 100

//边表结构
typedef struct EdgeNode
{
	int mark;//标志域 0 为未访问过 1 为访问过
	int ivex;//边的 i 端
	int jvex;//边的 j  端
	struct EdgeNode* ilink;//指向和  i  相关的边
	struct EdgeNode* jlink;//指向和  j  相关的边
	int weight;
}EdgeNode;

//顶点表结构
typedef struct VexNode
{
	char data;
	struct EdgeNode* firstedge;
}VexNode,AdjList[MAXSIZE];

//邻接多重表结构
typedef struct
{
	AdjList adjlist;
	int numv;
	int nume;
}AMLGraph;

隣接する複数のテーブルの作成:

void CreateAMLGraph(AMLGraph* G)
{
	int i, j, k, w;
	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("请输入边的两顶点在数组中的下标和边的权值:\n");
		while (getchar() != '\n');//清空缓冲区
		scanf("%d %d %d", &i, &j, &w);
		EdgeNode* e = (EdgeNode*)malloc(sizeof(EdgeNode));
		e->mark = 0;
		e->ivex = i;
		e->jvex = j;
		e->weight = w;
		e->ilink = G->adjlist[i].firstedge;
		e->jlink = G->adjlist[j].firstedge;
		G->adjlist[i].firstedge = e;
		G->adjlist[j].firstedge = e;
	}
}

通常のトラバーサル隣接するマルチテーブル:

void PrintAMLGraph(AMLGraph G)
{
	for (int i = 0; i < G.numv; i++)
	{
		EdgeNode* p = G.adjlist[i].firstedge;
		printf("和顶点 %c 有关的边有:", G.adjlist[i].data);
		while (p)
		{
			if (p->ivex == i)//判断时边的何端与 i 相等
			{
				//if (p->mark == 1)//当某条边是需要访问一次时采用标志变量,否则不用
				//{
					printf("%c 到 %c ,权值为 %d\t", G.adjlist[p->ivex].data, G.adjlist[p->jvex].data, p->weight);
					//p->mark = 1;
				//}
				p = p->ilink;
			}
			else
			{
				//if (p->mark == 0)
				//{
					printf("%c 到 %c ,权值为 %d\t", G.adjlist[p->jvex].data, G.adjlist[p->ivex].data, p->weight);
					//p->mark = 1;
				//}
				p = p->jlink;
			}
			printf("\n");
		}
	}
}

0×03。配列EDGEセット

意味:メモリマップの構造は、二次元アレイの頂点の一次元配列に格納された情報で構成され、配列の添字の各要素の側縁によって一次元配列情報格納されている側は、始端インデックス、重量構成。

説明:このエッジのメモリ構造注目セット、頂点操作必要に応じて、アレイの全体のエッジを横断する必要性、効率が低く、一般的に使用されていません。

 

 

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

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

おすすめ

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