== 1つ、問題の原因==
ツリー特性を持つ無向グラフの場合、ルートとして任意のノードを選択できます。したがって、グラフはツリーになる可能性があり、考えられるすべてのツリーの中で、高さが最小のツリーは最小の高さのツリーと呼ばれます。このようなグラフが与えられたら、すべての最小高さの木を見つけてそれらのルートノードを返す関数を記述します。グラフには、0からn-1のラベルが付いたn個のノードが含まれています。番号nと無向エッジのリスト(各エッジはラベルのペア)が与えられると、重複するエッジがエッジに表示されないと想定できます。すべてのエッジが無向エッジであるため、[0,1]と[1,0]は同じであり、同時にエッジに表示されることはありません。
例1:
入力:n = 4、エッジ= [[1、0]、[1、2]、[1、3]]
0
|
1
/ \
2 3
出力:[1]
例2:
入力:n = 6、エッジ= [[O、3]、[1、3]、[2、3]、[4,3]、[5、4]]
0 1 2
\ | /
3
|
4
|
5
出力:[3、4]
説明:
[ツリーの定義]によると、ツリーは無向グラフであり、任意の2つの頂点が1つのパスのみで接続されています。言い換えれば、単純なサイクルのない接続されたグラフはすべてツリーです。
ツリーの高さは、ルートノードとリーフノードの間の最長の下向きパスを指します。上端の数。
第二に、心の旅
C言語を使用して、要約で説明されている無向グラフで最小の高さの木を見つける問題を解決します。データ構造を学習していない初心者の場合、問題を解決するプロセス全体を理解するために、彼はほとんど髪を引っ掻きました。 。最初はインターネットで関連する問題解決方法を探していましたが、簡単な検索は古典的なリードコードの問題で、参照できるブログがたくさんあります。この瞬間、心が美しく、前任者の知恵も無料で使えます。しかし、物事が非常に単純である場合、今日の共有は生まれません。大きな期待を持ってブログを開き、C ++ / javaの実装を見たとき、私の壊れやすい小さな心は徐々にクールになりました。私はC ++を学んだことがなく、Javaも知りません。他に何をしますか?私はCですが、プログラミングの経験はまだあまりありません。私は何ができますか?私は彼らの問題解決のアイデアを見ました。ええと、無向グラフ、幅優先探索?トポロジー?見れば見るほど、この時期にパニックに陥ったグループ。わからないので耳を隠してベルを盗むことはしません。最初に自分で問題を分析し、データ構造の知識を補ってから、経験豊富な数人の同僚と話し合い、自分の問題解決のアイデアを整理することをお勧めします。
3つの問題解決のアイデア
無向グラフを作成する->無向グラフをトラバースする->対称性->リーフノードを順番に削除する
無向グラフは、固定小数点とエッジで構成されます。グラフを表現する方法はたくさんありますが、比較した結果、隣接行列を使用してグラフを表現することにしました。リンクリストよりも理解しやすく、隣接行列の無向グラフの対称性を使用することで、無向グラフの各頂点の次数を直感的に判断できます。
隣接行列を上の
図に示します。グラフの隣接行列は、グラフを表す2つの配列を使用して格納されます。1つは、頂点情報をグラフに格納するための配列と、2次元配列(隣接行列と呼ばれる)を意味して、グラフのエッジに関する情報を格納します。
このマトリックスを使用すると、図の情報を直感的に確認できます。
1.頂点間に接続があり、それらの側面の次数を1に設定します。
2.頂点の次数は、実際には隣接行列の固定小数点v(i)のi番目の行(またはi番目の列)の要素の合計です。たとえば、v(1の次数)は1 + 0 + 1 + 0 = 2です。
3.頂点v(i)のすべての隣接する点は、行列のi番目の行でarc(i)(j)が1である点です。
4.無向グラフの頂点は互いに向き合っているため、arc(i)(j)の値は主対角線上に対称的に分布しています。
隣接行列がトラバースされるたびに、次数1の頂点が取得されます。この頂点はツリー構造のリーフノードである必要があります。隣接行列の無向グラフの対称性の原理に従い、点と臨界点に対応する接続エッジの次数を0に設定します。つまり、葉を切る操作が完了します。探している最小の高さのツリーのルートノードである頂点が1〜2個残るまで、再帰的な操作を実行します。
4、例2のテスト
5、コード例(完全)
/*******************************************************************************
* Filename:
* FMHT
*Description:
* Find the Minimum Height Tree
*Author:
QH
*Time:
2020.8.24
********************************************************************************/
#include <stdio.h>
typedef int VertexType;
typedef int EdgeType;
#define MAXVEX 100
#define ZERO 0
typedef struct{
VertexType vexs[MAXVEX];
EdgeType arc[MAXVEX][MAXVEX];
int numVertexes, numEdges;
} MGraph;
void CreateMGraph(MGraph *G);
void RemoveLeave(MGraph *G);
int main(){
//Building undirected graph with adjacency matrix
MGraph G;
CreateMGraph(&G);
printf("Output the root node of the minimum height tree\n");
RemoveLeave(&G);
return 0;
}
/*******************************************************************************
*****************
* FUNCTION
* CreateMGraph
*DESCRIPTION
* Representstion of undirected graph by adjacency matrix.
*PARAMETERS
* G [MGraph *] structure
*RETURNS
* void
*****************
*******************************************************************************/
void CreateMGraph(MGraph *G){
int i, j, k;
printf("Please enter the number of vertexes and edges:");
scanf("%d,%d", &G -> numVertexes, &G -> numEdges);
printf("Please enter vertex:\n");
for (i = 0; i < G -> numVertexes; i ++)
scanf("%d", &G -> vexs[i]);
for (i = 0; i < G -> numVertexes; i ++)
for (j = 0; j < G -> numVertexes; j ++)
G -> arc[i][j] = ZERO;
for (k = 0; k < G -> numEdges; k ++){
printf("please enter (vi,vj):");
scanf("%d, %d", &i, &j);
G -> arc[i][j] = 1;
G -> arc[j][i] = G -> arc[i][j];
}
//Adjacency matrix of output undirected graph
printf("Adjacency matrix of output undirected graph:\n");
for (i = 0; i < G -> numVertexes; i ++){
for (j = 0; j < G -> numVertexes; j ++){
printf("%d\t", G -> arc[i][j]);
}
printf("\n");
}
}
/*******************************************************************************
*****************
* FUNCTION
* RemoveLeave
*DESCRIPTION
* Use recursive loops to remove leaf nodes layer by layer.
*PARAMETERS
* G [MGraph *] structure
*RETURNS
* void
*****************
*******************************************************************************/
void RemoveLeave(MGraph *G){
int i, j; //for circulation
int sum; //Sum of connected edges of each vertex
int n = 0; //Number of remaining vertices
int m[G -> numVertexes]; //save
//initialize m[]
for (i = 0; i < G -> numVertexes; i ++){
m[i] = ZERO;
}
//Determine whether the vertex is a leaf. yes set 1,not set 2
for (i = 0; i < G -> numVertexes; i ++){
sum = 0;
for (j = 0; j < G -> numVertexes; j ++){
sum = sum + G -> arc[i][j];
if (sum > 1){
n = n + 1;
m[i] = 2;
break;
}
if (sum == 1){
m[i] = 1; //leaf
}
}
}
//remove leaf
for (i = 0; i < G -> numVertexes; i ++){
if (m[i] == 1){
for (j = 0; j < G -> numVertexes; j ++){
G -> arc[i][j] = 0;
G -> arc[j][i] = 0;
}
}
if (m[i] == 2){
if (n < 3){
//Output the root node of the minimum height tree
printf("%d\t", G -> vexs[i]);
}
}
}
//Recursion and termination condition judgment
if (n < 3){
return ;
}
else{
RemoveLeave(G);
}
}