最小スパニングツリー
次は、最小スパニングツリーのコンテンツを導入することです。
最小スパニングツリーは何ですか?
定義:各辺のコストと最小スパニングツリーは、(最小コストのスパニングツリー)は、最小スパニングツリーと呼ばれる最小コストのスパニングツリー通信ネットワークと呼ばれます。
ツリーアルゴリズムは、最下部のスパニングツリーのプロパティのほとんどの使用である最小全域を形成する多くのアルゴリズムがあります。
特性:Nを仮定=(V、E)は、通信ネットワークであり、Uは、頂点Vの集合の空でない部分集合であります (u、v)はu∈Uは、v∈VUは、最小スパニングツリーが存在しなければならない最小量(または費用)側との一方がエッジ含んでいる場合には(U、V)の
要約すると、我々はこれらの条件を持っている必要があります。
- 通信ネットワークである(図通信)
- それぞれの側には、正しい値を持っています
あなたがわからない場合は、その者は、例をあげてみましょう:
我々はそれらすべてに通信するために、もちろん不可能の我々は、価格を考えると、我々はすべての都市のための接続のコストを最小限にするために使用する必要があり、なぜなら大都市の、n個の都市での連絡先のネットワークを構築する必要がありましょう。
?懸命にそれを行う方法(っ°Д°;)っ
私たちは、各都市を表現するために円を使用します
矢印に含まれる値は重みを表すと
私たちの質問は、どのように我々は、我々の目的を達成するために行くことを選ぶのですか?(我々の目的は、次のとおりDemacian D =====(¯▽¯*)bが....... ...コースの目的は、いくつかの経路、組成物重量の最小値を選択し、そしてすることができることです......上のこれらの接続点)
まず、我々は、我々は簡単にいくつかの経路を選択することができます.....あなたの目で観察します:
我々は、合計重みを計算する:1 + 2 + 4 + 5 + 12 = 24。はい、これは最小スパニングツリー構造であり、我々は選択したルートは間違っていないです。そこで質問が来ました。私たちは、選択する方法、それを?
私たちは道を選択したときに覚えていますか?私の考えは、最初の昇順で重みのそれぞれの側面によると、その後、排水のシーケンスで、エッジがある場合、すべてのポイントの完了は、当然のことながら、カバーするまで、私は必要なエッジを選択することで存在し、 2つの都市が(●∀●)を介して行っているので、2つの頂点の間でさえ、私にはない、となっています。
すべての頂点が接続されている場合、我々は、最小スパニングツリーを構成します。我々はそのため、このようなAシーケンスを排水している場合:
街 | 市は通過することができます | 重量 |
---|---|---|
A | B | 1 |
A | D | 2 |
B | F | 4 |
A | E | 5 |
E | F | 9 |
A | C | 12 |
B | C | 13 |
C | D | 18 |
D | E | 32 |
123456:それはデジタルABCDEFの対応に変換されます
私たちは、その後、選択は次のような状況大に小さいです。
我々は勝ち点6を持っているので、私たちは、私たちに必要な最小スパニングツリーを完成し、5つの辺を選択します。はい、これは私が言うのアルゴリズム最小スパニングツリーは、次のとおりです。(クラスカルクラスカルのアルゴリズム)
公式の建設プロセスの比較です。
- N個のサイド・バイ・重量昇順に、通信ネットワークN =(V、E)を仮定
- 図無通信は、図通信自己完結型の構成要素の各頂点のみ初期の状態Nの頂点とエンドレスT =(V、{})です。
- 取り付けられたエッジの頂点が異なる連結成分にはT(すなわち、何ループが形成されていない)に入る場合は、エッジEで最小重量を選択し、これをT側に追加され、それ以外の場合、このエッジは、選択された丸め最小重量エッジ
- 同じ連結成分にTまで、すべての頂点まで繰り返し
公式の説明の波、(@ _ @)私は少し無知見えたが、全ての権利は、私は自分自身を理解しています。次は、その実装するコードです......
main.cppに
#include"GraphKruskal.h"
int main()
{
GraphKurskal g1;
g1.Init();
g1.Kruskal();
g1.Display();
return 0;
}
/*
输入样例:
1 1 1
1 4 2
2 6 4
1 5 5
5 6 9
1 3 12
2 3 13
3 4 18
4 5 32
*/
GraphKruskal.h
#pragma once
#ifndef _GRAPHKRUSKAL_H_
#define _GRAPHKRUSKAL_H_
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<vector>
using namespace std;
// 这是利用邻接矩阵来实现的克鲁斯卡尔搜索最小生成树的算法
struct node
{
int from, to;
int sideID;//记录边号,已选定可以输出的边
int distance;
};
class GraphKurskal
{
private:
vector<node>graph;//记录边
vector<bool>visited;//是否经历过
vector<int>IDofSide;//每条边的ID
int minDistacne;//最小权值
int nodeNumber;//几个点
//void Sort();//这个程序是调用库函数的sort函数进行排序,因此没有写自定义sort函数
public:
void Init();//初始化
void Kruskal();//进行克鲁斯卡尔算法,找到最小生成树
void Display();//显示
};
bool cmp(node a1,node a2);//从小到大排序的函数
#endif // !_GRAPHKRUSKAL_H_
GraphKruskal.cpp
#include "GraphKruskal.h"
void GraphKurskal::Init()
{
node n1;
int i = 0;
cout << "请输入有几个点" << endl;
cin >> nodeNumber;
visited.resize(nodeNumber + 1, false);
cout << "请输入各边的关系,'#'结束" << endl;
cout << "请按照格式:开始点---终止点---距离" << endl;
while ((cin >> n1.from&& n1.from != '#') && (cin >> n1.to&& n1.to != '#'))
{
cin >> n1.distance;
n1.sideID = ++i;
graph.push_back(n1);
}
}
void GraphKurskal::Kruskal()
{
sort(graph.begin(), graph.end(),cmp);//进行函数比较
//当选择的边数不为节点数减一的情况,我们继续循环
minDistacne = 0;
for (int i = 0; i < graph.size(); i++)
{
//判断图中的点是否遍历过,如果遍历过,那么跳过,否则继续遍历
if (!visited[graph[i].from] || !visited[graph[i].to])
{
visited[graph[i].from] = true;
visited[graph[i].to] = true;
IDofSide.push_back(graph[i].sideID);
minDistacne += graph[i].distance;
if (IDofSide.size() == nodeNumber - 1)
break;
}
}
}
void GraphKurskal::Display()
{
cout << "总距离是:" << minDistacne << endl<<"权边是:";
for (int i = 0; i < IDofSide.size(); i++)
cout << graph[IDofSide[i]-1].distance << " ";
cout << endl;
}
bool cmp(node a1, node a2)
{
return a1.distance > a2.distance ? false : true;
}
結果を達成するためのコード:
「|バージョン2のデータ構造C言語のバージョンを」学びます