优先级队列解决top-K问题(C语言实现)

对于数组{10, 4, 3, 6, 5, 8, 9, 3},希望求第k (k = 3) 大的数据。
如果用传统的思路解决这个问题:先用快速排序对整个数组排序。然后取第K个元素,这种方式的时间复杂度为O(N * logN)。如果n非常大,对整个数组排序需要使用外部排序 (内存中放不下,需要硬盘辅助排序)。如果使用大小为k的小顶堆,就有可能在内存中完成这个任务。也就是说,这个方法不仅可以降低时间复杂度,还可以降低内存的消耗。

这里用小顶堆的方式进行计算:取前面3个元素,建立一个小顶堆,然后遍历其它元素,如果某个元素比堆顶元素还要小,则丢弃该元素;如果该元素比堆顶元素大,则用它代替堆顶元素,并维护这个堆。最后,这个堆中的元素就是这个数组中最大的三个元素,这个堆顶元素就是第3大的数据。如果希望得到的是最大的3个数据,输出这个堆中的三个元素即可。

这个堆一共k个元素,所以维护一次堆的时间复杂度为O(logK)。遍历(N - k)个元素,并维护堆的时间复杂度为O((N - k) * logK)。
最好的情况,K = 1,不需要维护堆,所以时间复杂度为O(N);最差的情况,K = N,也就是用小顶堆求最小的那个元素,这时几乎所有时间都花费在建立一个大小为N的小顶堆,时间复杂度为O(N * logN)。与进行堆排序后取第K个元素的时间复杂度一样。但是如果是这种情况,用大顶堆计算,时间复杂度又是O(N);平均情况,如果K == N / 2,则时间复杂度为O(N * logN);一般情况下,k的值远小于N,所以时间复杂度为O(N * logK)。

这种求top-K的方法属于部分排序。如果k < logN,可以考虑用选择排序,如果k >= logN,可以使用本方法。

完整的代码如下:

#include <stdio.h>
#include <stdlib.h>

int arr [] = {
   10, 4, 3, 6, 5, 8, 9, 3};
int sizeOfHeap = 3; //第k (k = 3) 大的数据,维护一个大小为3的小顶堆
int size = 0; //数组的大小 

void swap(int i, int j) //交换数组arr中编号为i和j的两个元素 
{
   
    int temp = arr[i];
    arr[i] = arr[j]
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
软件介绍: ArrayNetworksL3Setu是移动代理点客户端软件,也就是常说的那个红A。需要安装这个软件后才能登陆。BOSS 客户端更新说明为了解决现有BOSS系统BUG,现在需要升级各代办点终端的SSL 的插件,具体插件步骤如下:1.将附件中名称为:“ArrayNetworksL3OnlyWebSetup.zip”的安装包拷贝到代办终端上。 2.在代办终端上解压该文件3.点击“setup.exe”4.一步步安装首先remove现有的插件。点击“next”,点击“finish”,再点击“setup.exe”,点击“finish”完成安装。完成后开始使用,打开IE浏览器。输入移动 IP地址。IE版本可能会出现,点击“允许”,当右下角出现“A” 上面出现8.4.6.80确认为新的插件版本。出现红A,没有任何报错就表示安装正常。-----------------------------------------------------------------------------------------------------如果安装有问题或者不能正常访问,请单独安装客户端。安装的文件名称ArrayNetworksL3SetupX32.zip,ArrayNetworksL3SetupX64.zip请对应系统的版本安装1查看自己的系统的版本,32位,64位2.“计算机”-->“属性”查看自己的是32位的还是64位的操作系统。请对应版本安装。4.安装客户端软件的步骤,首先解压文件。点击 “setup.exe”安装完成。打开IE登陆SSL 如重启失败请重置浏览器的高级设置。点击---“还远高级设置”---“确定”再次登陆
装载问题是一个经典的组合优化问题,其目标是在有限的容量下尽可能多地装载物品。分支限界法是一种常用的解决组合优化问题算法,可以用来求解装载问题。 以下是使用优先队列式分支限界法求解装载问题C语言代码: ```c #include <stdio.h> #include <stdlib.h> #include <queue> using namespace std; const int MAX_N = 100; // 最大物品数 const int MAX_C = 1000; // 最大容量 int N, C; // 物品数、容量 int w[MAX_N]; // 物品重量 int best; // 目前最优解 int cnt; // 记录扩展结点数 struct Node { int level; // 扩展结点所在的层数(即装入的物品数) int weight; // 当前已经装载的重量 int value; // 当前已经装载的价值 bool operator<(const Node& n) const { // 定义优先级队列的比较方式 return value < n.value; } }; priority_queue<Node> PQ; // 优先级队列 // 计算下界 int bound(int level, int weight, int value) { int bound = value; for (int i = level; i < N; i++) { if (weight + w[i] <= C) { weight += w[i]; bound += w[i]; } else { bound += (C - weight) * 1.0 / w[i] * value; break; } } return bound; } // 分支限界法求解 void solve() { Node u, v; u.level = u.weight = u.value = 0; // 根结点 PQ.push(u); while (!PQ.empty()) { u = PQ.top(); PQ.pop(); if (u.value < best) { continue; } if (u.level == N) { best = u.value; continue; } cnt++; v.level = u.level + 1; v.weight = u.weight + w[v.level - 1]; v.value = u.value + w[v.level - 1]; if (v.weight <= C && v.value > best) { best = v.value; } if (bound(v.level, v.weight, v.value) > best) { PQ.push(v); // 左儿子结点入队 } v.weight = u.weight; v.value = u.value; if (bound(v.level, v.weight, v.value) > best) { PQ.push(v); // 右儿子结点入队 } } } int main() { scanf("%d %d", &N, &C); for (int i = 0; i < N; i++) { scanf("%d", &w[i]); } best = 0; solve(); printf("最优解:%d\n", best); printf("扩展结点数:%d\n", cnt); return 0; } ``` 在代码中,我们使用一个优先级队列来维护当前扩展结点的集合,每次从中选取价值最大的结点进行扩展。在计算下界时,我们采用了一种贪心策略,即将剩余容量装满当前价值最高的物品。对于每个扩展结点,我们都生成两个子结点,一个是装入当前物品的子结点,另一个是不装入当前物品的子结点。如果一个子结点的下界大于目前的最优解,就将其加入优先级队列中,否则就剪枝。最终,当队列为空时,我们就得到了最优解。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值