大体思路:
1.选取数据结构建堆:没什么好说的,堆是完全二叉树,用数组建堆
2.插入节点(建堆过程):每次向数组末尾插入节点,然后比较该节点与父亲节点的大小关系。举最小堆为例,若h[pos]>h[pos/2](子节点比父节点大),就交换两个节点,完成节点上移操作
注意:我们初始化堆数组为一个非常小的值,目的是在h[0]设立哨兵,以增加代码可读性
代码:
int h[1005]={-10005}; void heapCreate(int h[], int pos) { //设立哨兵,当pos=1时,这个循环就结束了,否则h[0]=0,陷入死循环 while(h[pos/2]>h[pos]){ swap(h[pos/2],h[pos]); pos/=2; } }
3.打印路径
代码:
void path(int h[], int pos) { while(pos) { printf("%d%c",h[pos]," \n"[pos==1]); pos/=2; } }
插入和打印路径操作复杂度全部为树的高度,即lgn
全部代码:
#include <bits/stdc++.h> using namespace std; int n, m, h[1005]={-10005}; void heapCreate(int h[], int pos) { while(h[pos/2]>h[pos]){ swap(h[pos/2],h[pos]); pos/=2; } } void path(int h[], int pos) { while(pos) { printf("%d%c",h[pos]," \n"[pos==1]); pos/=2; } } int main() { cin>>n>>m; for(int i=1;i<=n;++i) { cin>>h[i]; heapCreate(h, i); //if(i==5) for(int j=1;j<=i;++j) printf("%d%c",h[j]," \n"[j==i]); } for(int i=1;i<=m;++i){ int pos;cin>>pos; path(h, pos); } return 0; }