12.6 使用动态分配的vector<int>输入和打印vector

本文介绍了一个使用C++实现的控制台应用程序,该程序通过智能指针管理和操作动态分配的向量,包括创建、读取和输出元素。演示了如何使用shared_ptr来替代裸指针,提高内存安全性和资源管理效率。
// Demo.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>


using namespace std;

vector<int> *create(vector<int>::size_type i) {
   return new (nothrow) vector<int>(i);
}

vector<int> *read(vector<int> *vp) {
   cout << "Please enter the elements" << endl;
   size_t times = vp->size();
   int tmp;
   for (int i = 0; i < times; ++i) {
      cin >> tmp;
      (*vp)[i] = tmp;
   }
   return vp;
}

void output(vector<int> *vp) {
   cout << "Output the elements" << endl;
   size_t times = vp->size();
   for (int i = 0; i < times; ++i) {
      cout << (*vp)[i] << " ";
   }
   cout << endl;
}

int main()
{
   cout << "Please enter the vector size" << endl;
   size_t vectorSize;
   cin >> vectorSize;
   vector<int> *vp = create(vectorSize);
   output(read(vp));
   delete vp;
   vp = nullptr;

   return 0;
}

使用智能指针:

shared_ptr<vector<int>> create(vector<int>::size_type i) {
   return make_shared<vector<int>>(i);
}

shared_ptr<vector<int>> read(shared_ptr<vector<int>> vp) {
   cout << "Please enter the elements" << endl;
   size_t times = vp->size();
   int tmp;
   for (int i = 0; i < times; ++i) {
      cin >> tmp;
      (*vp)[i] = tmp;
   }
   return vp;
}

void output(shared_ptr<vector<int>> vp) {
   cout << "Output the elements" << endl;
   size_t times = vp->size();
   for (int i = 0; i < times; ++i) {
      cout << (*vp)[i] << " ";
   }
   cout << endl;
}

int main()
{
   cout << "Please enter the vector size" << endl;
   size_t vectorSize;
   cin >> vectorSize;
   shared_ptr<vector<int>> vp = create(vectorSize);
   output(read(vp));

   return 0;
}
(在您提供的代码中,dbscanParallel函数中包含了一个注释掉的部分,这部分代码是用来输出噪声点(即被标记为-1的点)的。当这部分代码被注释掉时,程序不会输出任何噪声点信息。 从您提供的截图来看,当代码运行时,如果包含输出噪声点的代码被注释掉,那么并行串行的输出结果会有所不同,因为串行版本中噪声点的检测标记是同步进行的,而并行版本中这部分工作被多个线程并发执行。这可能导致并行版本的噪声点检测结果与串行版本不一致。 此外,由于并行执行时多个线程同时访问修改共享数据(如labels数组),如果没有适当的同步机制(如原子操作或互斥锁),可能会导致数据竞争不一致的结果。)根据以上描述改进代码:#include <fstream> #include <iostream> #include <vector> #include <cmath> #include <sstream> #include <string> #include <unordered_set> #include <chrono> #include <algorithm> #include <omp.h> #include <atomic> #include <mutex> struct Point { std::vector<double> values; }; double euclideanDistance(const Point& p1, const Point& p2) { double sum = 0.0; for (size_t i = 0; i < p1.values.size(); ++i) { sum += (p1.values[i] - p2.values[i]) * (p1.values[i] - p2.values[i]); } return std::sqrt(sum); } void dbscanParallel(const std::vector<Point>& points, double eps, int minPts, std::vector<int>& labels) { std::atomic<int> label(0); std::vector<std::atomic<bool>> visited(points.size()); for (auto& v : visited) v.store(false, std::memory_order_relaxed); std::vector<int> noise; #pragma omp parallel { std::vector<int> local_noise; #pragma omp for schedule(dynamic) for (int i = 0; i < points.size(); ++i) { bool expected = false; if (visited[i].compare_exchange_strong(expected, true)) { std::unordered_set<int> neighbors; // 串行计算邻居 for (int j = 0; j < points.size(); ++j) { if (i != j && euclideanDistance(points[i], points[j]) <= eps) { neighbors.insert(j); } } if (neighbors.size() < minPts) { labels[i] = -1; local_noise.push_back(i); } else { int current_label = label.fetch_add(1, std::memory_order_relaxed); labels[i] = current_label; std::vector<int> seeds(neighbors.begin(), neighbors.end()); for (size_t k = 0; k < seeds.size(); ++k) { int seed = seeds[k]; bool seed_expected = false; if (visited[seed].compare_exchange_strong(seed_expected, true)) { labels[seed] = current_label; // 扩展新邻居 std::unordered_set<int> new_neighbors; for (int j = 0; j < points.size(); ++j) { if (j != seed && !visited[j].load(std::memory_order_relaxed) && euclideanDistance(points[seed], points[j]) <= eps) { new_neighbors.insert(j); } } if (new_neighbors.size() >= minPts) { seeds.insert(seeds.end(), new_neighbors.begin(), new_neighbors.end()); } } } } } } #pragma omp critical noise.insert(noise.end(), local_noise.begin(), local_noise.end()); } /*if (!noise.empty()) { std::cout << "Noise points:" << std::endl; for (int idx : noise) { std::cout << "Point " << idx << ": "; for (double val : points[idx].values) { std::cout << val << " "; } std::cout << std::endl; } } else { std::cout << "No noise points detected." << std::endl; }*/ } // 其他函数(如readCSV、dbscanSerial)保持不变 std::vector<Point> readCSV(const std::string& filename) { std::vector<Point> points; std::ifstream file(filename); std::string line; while (std::getline(file, line)) { std::istringstream iss(line); std::string token; Point point; while (std::getline(iss, token, ',')) { point.values.push_back(std::stod(token)); } points.push_back(point); } return points; } void dbscanSerial(const std::vector<Point>& points, double eps, int minPts, std::vector<int>& labels) { int label = 0; std::vector<bool> visited(points.size(), false); std::vector<int> noise; for (int i = 0; i < points.size(); ++i) { if (!visited[i]) { std::unordered_set<int> neighbors; for (int j = 0; j < points.size(); ++j) { if (i != j && euclideanDistance(points[i], points[j]) <= eps) { neighbors.insert(j); } } if (neighbors.size() < minPts) { labels[i] = -1; // Mark as noise noise.push_back(i); } else { label = ++label; std::unordered_set<int> seeds = neighbors; while (!seeds.empty()) { int seed = *seeds.begin(); seeds.erase(seeds.begin()); visited[seed] = true; labels[seed] = label; std::unordered_set<int> new_neighbors; for (int j = 0; j < points.size(); ++j) { if (!visited[j] && euclideanDistance(points[seed], points[j]) <= eps) { new_neighbors.insert(j); } } for (int j : new_neighbors) { if (neighbors.find(j) == neighbors.end()) { seeds.insert(j); neighbors.insert(j); } } } for (auto it = neighbors.begin(); it != neighbors.end(); ++it) { visited[*it] = true; labels[*it] = label; } } } } /*if (!noise.empty()) { std::cout << "Noise points:" << std::endl; for (int idx : noise) { std::cout << "Point " << idx << ": "; for (double val : points[idx].values) { std::cout << val << " "; } std::cout << std::endl; } } else { std::cout << "No noise points detected." << std::endl; }*/ } int main(int argc, char** argv) { int num_threads = 4; // Default number of threads if (argc > 1) { num_threads = std::stoi(argv[1]); } omp_set_num_threads(num_threads); auto points = readCSV("D:\\桌面\\并行程序\\naiveBayes\\naiveBayes\\iris.csv"); double eps = 0.5; // Epsilon value int minPts = 5; // Minimum points to form a dense region std::vector<int> labels(points.size(), 0); // Serial DBSCAN auto startSerial = std::chrono::high_resolution_clock::now(); dbscanSerial(points, eps, minPts, labels); auto endSerial = std::chrono::high_resolution_clock::now(); std::chrono::duration<double> elapsedSerial = endSerial - startSerial; // Parallel DBSCAN std::fill(labels.begin(), labels.end(), 0); auto startParallel = std::chrono::high_resolution_clock::now(); dbscanParallel(points, eps, minPts, labels); auto endParallel = std::chrono::high_resolution_clock::now(); std::chrono::duration<double> elapsedParallel = endParallel - startParallel; // Calculate speedup and efficiency double speedup = elapsedSerial.count() / elapsedParallel.count(); double efficiency = (speedup / num_threads) * 100; // Print performance results std::cout << "\nPerformance Results:" << std::endl; std::cout << "+------------+----------------+------------------+--------------+----------------+" << std::endl; std::cout << "| Threads | Serial Time (s)| Parallel Time (s)| Speedup | Efficiency (%) |" << std::endl; std::cout << "+------------+----------------+------------------+--------------+----------------+" << std::endl; printf("| %-10d | %-14.6f | %-16.6f | %-12.6f | %-14.2f |\n", num_threads, elapsedSerial.count(), elapsedParallel.count(), speedup, efficiency); std::cout << "+------------+----------------+------------------+--------------+----------------+" << std::endl; return 0; }
05-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值