[C++][algorithm] 使用C++实现TopK算法

1 简介

在数据挖掘和大数据处理领域,TopK问题是一个常见的问题,它要求从一组数据中找出最大的K个元素。这个问题在很多实际应用中都有出现,比如搜索引擎的关键字提取、推荐系统中的热门商品推荐等。TopK算法因其高效性和实用性,成为算法工程师和数据科学家必须掌握的技能之一。

2 代码实现

template<typename T>
bool TopK(const void *input_tensor_pointer,
		  size_t input_tensor_size,
		  std::vector<int64_t> &output_index,
		  std::vector<float> &output_tensor,
		  size_t k,
		  T min_confidence) {
  // 使用最小堆来保存 TopK 元素,最小堆的每一个元素为{float confidence, int index}并将使用std::pair来表示
  std::priority_queue<std::pair<T, int64_t>, std::vector<std::pair<T, int64_t>>, std::greater<>> min_heap;

  // 将数据插入到最小堆中
  auto temp_input_tensor_pointer = reinterpret_cast<const T *>(input_tensor_pointer);
  for (int64_t i = 0; i < input_tensor_size; i++) {
	if (temp_input_tensor_pointer[i] < min_confidence) {
	  continue;
	}

	min_heap.emplace(temp_input_tensor_pointer[i], i);
	// 如果堆的大小超过 K,弹出堆顶元素
	if (min_heap.size() > k) {
	  min_heap.pop();
	}
  }

  while (!min_heap.empty()) {
	output_tensor.emplace_back(min_heap.top().first);
	output_index.emplace_back(min_heap.top().second);
	min_heap.pop();
  }
  std::reverse(output_index.begin(), output_index.end());
  std::reverse(output_tensor.begin(), output_tensor.end());
  return true;
}
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是双向Astar算法的C++代码实现,供您参考: ```cpp #include <iostream> #include <queue> #include <set> #include <vector> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f struct Node { int x, y, f, g, h; // 行、列、估价函数、起点到当前点的距离、当前点到终点的估价距离 bool operator <(const Node &b) const { // 重载小于运算符 return f > b.f; // 按f值从小到大排序 } }; const int MAXN = 1005; int n, m, ans; char map[MAXN][MAXN]; vector<Node> vec[MAXN][MAXN]; // 存储每个点可以到达的点 int dis[MAXN][MAXN], vis[MAXN][MAXN]; // dis数组记录起点到每个点的距离,vis数组记录是否访问过该点 int dx[]{0, 0, 1, -1}; int dy[]{1, -1, 0, 0}; // 从起点开始搜索 void Astar(Node start, Node end) { priority_queue<Node> q1, q2; // 分别存储正反两个方向的搜索队列 memset(dis, INF, sizeof(dis)); // 初始化dis数组 memset(vis, 0, sizeof(vis)); // 初始化vis数组 start.f = start.g + start.h; // 计算起点的f值 end.f = end.g + end.h; // 计算终点的f值 q1.push(start); // 将起点加入正向搜索队列 q2.push(end); // 将终点加入反向搜索队列 dis[start.x][start.y] = 0; // 起点到自己的距离为0 dis[end.x][end.y] = 0; // 终点到自己的距离为0 while (!q1.empty() && !q2.empty()) { // 当两个队列都不为空时,继续搜索 Node u; if (q1.top().f <= q2.top().f) { // 选择f值小的队列进行搜索 u = q1.top(); // 取出正向搜索队列中的队首元素 q1.pop(); // 弹出队首元素 if (vis[u.x][u.y]) { // 如果这个点已经被访问过了,就跳过 continue; } vis[u.x][u.y] = 1; // 标记这个点已经被访问过了 for (int i = 0; i < vec[u.x][u.y].size(); i++) { // 遍历这个点可以到达的所有点 Node v = vec[u.x][u.y][i]; if (!vis[v.x][v.y]) { // 如果这个点没有被访问过 int d = u.g + v.g; // 计算起点到当前点的距离 if (d < dis[v.x][v.y]) { // 如果当前点到起点的距离比原来计算的距离要小 dis[v.x][v.y] = d; // 更新起点到当前点的距离 v.g = d; // 更新当前点到起点的距离 v.f = v.g + v.h; // 更新当前点的f值 q1.push(v); // 将当前点加入正向搜索队列 } } else { // 如果这个点已经被访问过了 ans = min(ans, dis[u.x][u.y] + dis[v.x][v.y] + v.g); // 更新最短路 } } } else { // 选择f值小的队列进行搜索 u = q2.top(); // 取出反向搜索队列中的队首元素 q2.pop(); // 弹出队首元素 if (vis[u.x][u.y]) { // 如果这个点已经被访问过了,就跳过 continue; } vis[u.x][u.y] = 1; // 标记这个点已经被访问过了 for (int i = 0; i < vec[u.x][u.y].size(); i++) { // 遍历这个点可以到达的所有点 Node v = vec[u.x][u.y][i]; if (!vis[v.x][v.y]) { // 如果这个点没有被访问过 int d = u.g + v.g; // 计算终点到当前点的距离 if (d < dis[v.x][v.y]) { // 如果当前点到终点的距离比原来计算的距离要小 dis[v.x][v.y] = d; // 更新终点到当前点的距离 v.g = d; // 更新当前点到终点的距离 v.f = v.g + v.h; // 更新当前点的f值 q2.push(v); // 将当前点加入反向搜索队列 } } else { // 如果这个点已经被访问过了 ans = min(ans, dis[u.x][u.y] + dis[v.x][v.y] + v.g); // 更新最短路 } } } } } int main() { cin >> n >> m; Node start, end; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> map[i][j]; if (map[i][j] == 'S') { // 找到起点 start.x = i; start.y = j; start.g = 0; start.h = abs(i - n) + abs(j - m); // 计算起点到终点的曼哈顿距离 start.f = start.g + start.h; } if (map[i][j] == 'E') { // 找到终点 end.x = i; end.y = j; end.g = 0; end.h = abs(i - start.x) + abs(j - start.y); // 计算终点到起点的曼哈顿距离 end.f = end.g + end.h; } } } for (int i = 1; i <= n; i++) { // 预处理每个点可以到达的点 for (int j = 1; j <= m; j++) { if (map[i][j] != '#') { // 如果当前点不是障碍物 for (int k = 0; k < 4; k++) { // 向四个方向搜索 int nx = i + dx[k]; int ny = j + dy[k]; if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && map[nx][ny] != '#') { // 如果可以到达 Node node; node.x = nx; node.y = ny; node.g = 1; // 计算当前点到邻居点的距离为1 node.h = abs(nx - end.x) + abs(ny - end.y); // 计算邻居点到终点的曼哈顿距离 node.f = node.g + node.h; // 计算邻居点的f值 vec[i][j].push_back(node); // 将邻居点加入到当前点可以到达的点的集合中 } } } } } ans = INF; // 初始化最短路为无穷大 Astar(start, end); // 开始双向Astar搜索 cout << ans << endl; // 输出最短路 return 0; } ``` 注:以上代码仅供参考,实际应用中可能需要根据具体情况进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值