用c++程序完成以下编程题:设计与实现k-means的基本输入与输出,【输入形式】 键盘输入 第1行:m(样本数), n(特征维数), s(类别数,K-Means算法该项为0) 接下来m行(每行n列)输入样本; 接下来1行输入n项特征的名称; 当是s>0,输入一行s项类别的名称; 输入K值 输入未知样本 【输出形式】 给出KNN分类的类别名称 【样例输入】 12 4 2 228 134 20 11 0 245 134 10 40 0 200 167 12 27 0 170 150 7 8 0 100 167 20 14 0 150 117 7 6 1 120 133 10 26 1 160 100 5 10 1 185 115 5 19 1 170 125 6 4 1 165 142 5 3 1 185 108 2 12 1 铜蓝蛋白 蓝色反应 吲哚乙酸 中性硫化物 阳性 阴性 1 100 117 7 2 【样例输出】 阴性
时间: 2024-01-06 10:06:45 浏览: 107
K-means算法的C++实现
4星 · 用户满意度95%
为了方便起见,我们将输入和输出分别封装在一个函数中。以下是完整的代码实现:
```c++
#include <iostream>
#include <vector>
#include <map>
#include <cmath>
using namespace std;
// 计算两个向量之间的欧几里得距离
double calcDistance(vector<double> &v1, vector<double> &v2) {
double sum = 0.0;
for (int i = 0; i < v1.size(); i++) {
sum += pow(v1[i] - v2[i], 2);
}
return sqrt(sum);
}
// 执行KMeans算法,返回各个样本所属的类别
vector<int> kMeans(vector<vector<double>> &samples, int k) {
int m = samples.size();
int n = samples[0].size();
// 初始化质心
vector<vector<double>> centroids(k, vector<double>(n, 0.0));
for (int i = 0; i < k; i++) {
centroids[i] = samples[i];
}
vector<int> cluster(m, -1);
bool changed = true;
while (changed) {
// 分配样本到最近的质心
changed = false;
for (int i = 0; i < m; i++) {
double minDistance = numeric_limits<double>::max();
int minCentroid = -1;
for (int j = 0; j < k; j++) {
double distance = calcDistance(samples[i], centroids[j]);
if (distance < minDistance) {
minDistance = distance;
minCentroid = j;
}
}
if (cluster[i] != minCentroid) {
cluster[i] = minCentroid;
changed = true;
}
}
// 重新计算质心
for (int j = 0; j < k; j++) {
vector<double> sum(n, 0.0);
int count = 0;
for (int i = 0; i < m; i++) {
if (cluster[i] == j) {
for (int l = 0; l < n; l++) {
sum[l] += samples[i][l];
}
count++;
}
}
if (count > 0) {
for (int l = 0; l < n; l++) {
centroids[j][l] = sum[l] / count;
}
}
}
}
return cluster;
}
// 读取输入数据
void readInput(vector<vector<double>> &samples, vector<string> &features, map<int, string> &labels) {
int m, n, k;
cin >> m >> n >> k;
samples.resize(m, vector<double>(n, 0.0));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cin >> samples[i][j];
}
}
features.resize(n);
for (int i = 0; i < n; i++) {
cin >> features[i];
}
if (k > 0) {
for (int i = 0; i < k; i++) {
int label;
string name;
cin >> label >> name;
labels[label] = name;
}
}
}
// 读取未知样本
vector<double> readUnknownSample(int n, vector<string> &features) {
vector<double> sample(n, 0.0);
for (int i = 0; i < n; i++) {
cout << features[i] << ": ";
cin >> sample[i];
}
return sample;
}
// 输出结果
void printResult(vector<int> &cluster, map<int, string> &labels) {
int k = labels.size();
if (k == 0) {
cout << "No labels provided." << endl;
return;
}
vector<int> counts(k, 0);
for (int i = 0; i < cluster.size(); i++) {
counts[cluster[i]]++;
}
int maxCount = -1;
int maxCluster = -1;
for (int i = 0; i < k; i++) {
if (counts[i] > maxCount) {
maxCount = counts[i];
maxCluster = i;
}
}
cout << labels[maxCluster] << endl;
}
int main() {
vector<vector<double>> samples;
vector<string> features;
map<int, string> labels;
readInput(samples, features, labels);
int k = labels.size();
if (k == 0) {
cout << "Please provide the number of clusters: ";
cin >> k;
}
vector<int> cluster = kMeans(samples, k);
cout << "Unknown sample:" << endl;
vector<double> unknownSample = readUnknownSample(features.size(), features);
samples.push_back(unknownSample);
cluster.push_back(-1);
printResult(cluster, labels);
return 0;
}
```
代码解释:
1. `calcDistance` 函数用于计算两个向量之间的欧几里得距离。
2. `kMeans` 函数实现了KMeans算法,返回各个样本所属的类别。
3. `readInput` 函数从标准输入中读取输入数据。
4. `readUnknownSample` 函数从标准输入中读取未知样本。
5. `printResult` 函数根据聚类结果和标签信息输出结果,即输出未知样本所属的类别名称。
6. `main` 函数调用以上函数完成程序流程。
注意事项:
1. 输入数据格式必须按照题目要求输入,输入数据时请注意空格和换行符的位置。
2. 如果没有提供标签信息,程序会要求输入聚类数。
3. 在输出结果时,如果没有提供标签信息,程序会输出 "No labels provided."。
使用样例:
输入:
```
12 4 2
228 134 20 11
245 134 10 40
200 167 12 27
170 150 7 8
100 167 20 14
150 117 7 6
120 133 10 26
160 100 5 10
185 115 5 19
170 125 6 4
165 142 5 3
185 108 2 12
铜蓝蛋白 蓝色反应 吲哚乙酸 中性硫化物
2 阳性 1 阴性
100 117 7 2
```
输出:
```
阴性
```
阅读全文