将一系列给定数字依次插入一个初始为空的小顶堆H[]
。随后对任意给定的下标i
,打印从H[i]
到根结点的路径。
输入格式:
每组测试第1行包含2个正整数N和M(≤1000),分别是插入元素的个数、以及需要打印的路径条数。下一行给出区间[-10000, 10000]内的N个要被插入一个初始为空的小顶堆的整数。最后一行给出M个下标。
输出格式:
对输入中给出的每个下标i
,在一行中输出从H[i]
到根结点的路径上的数据。数字间以1个空格分隔,行末不得有多余空格。
输入样例:
5 3
46 23 26 24 10
5 4 3
输出样例:
24 23 10
46 23 10
26 10
创建小顶堆,然后去输出路径即可:
创建小顶堆的方法有两种:
1.插入法 时间复杂度为O(NlogN)
//堆中的路径
#include<stdio.h>
#include<stdlib.h>
#define maxsize 1005
#define mindata -10005
typedef struct h
{
int *data;
int size;
int capacity;
}* minheap;
minheap CreateHeap()
{
minheap h = (minheap)malloc(sizeof(struct h));
h->data = (int *)malloc(maxsize*sizeof(int));
h->size = 0;
h->capacity = maxsize;
h->data[0] = mindata;
return h;
}
int isFull(minheap h)
{
return h->size == h->capacity;
}
int insert(minheap h, int x)
{
int i;
if (isFull(h))
{
return 0;
}
i = ++(h->size);
for (; h->data[i / 2] > x; i /= 2)//上滤
h->data[i] = h->data[i / 2];
h->data[i] = x;
return 1;
}
void printPath(minheap h,int i)
{
for (; i>1; i /= 2)
printf("%d ", h->data[i]);
printf("%d\n", h->data[i]);
}
int main()
{
int n, m;
minheap h = CreateHeap();
scanf("%d %d", &n, &m);
int i,val;
for (i = 0; i < n; i++)
{
scanf("%d", &val);
insert(h,val);
}
//for (i = 1; i <= h->size; i++)
// printf("%d ", h->data[i]);
for (i = 0; i < m; i++)
{
scanf("%d", &val);
printPath(h,val);
}
return 0;
}
2.这个方法时间复杂度是O(N),线性的时间复杂度,更加高效。
该方法分两步:第一步,将N个元素按顺序存入二叉树中,这一步只需要满足完全二叉树的结构特性,而暂时不管其有序性。第二步,调整各节点元素,以满足最大堆的有序性。
但是我们知道对于数据相同的小顶堆,其存在形式不止一种。而这种构造出来的小顶堆是不符合题意的(doge)。
#include<stdio.h>
#include<stdlib.h>
#define maxsize 1005
#define mindata -10005
typedef struct h
{
int *data;
int size;
int capacity;
}* minheap;
minheap CreateHeap()
{
minheap h = (minheap)malloc(sizeof(struct h));
h->data = (int*)malloc(maxsize*sizeof(int));
h->size = 0;
h->capacity = maxsize;
h->data[0] = mindata;
return h;
}
void printPath(minheap h,int i)
{
for (; i>1; i /= 2)
printf("%d ", h->data[i]);
printf("%d\n", h->data[i]);
}
minheap PercDown(minheap h, int p)
{
int parent, child;
int x;
x = h->data[p];
//调整的实质的将p下滤
for (parent = p; parent * 2 <= h->size; parent = child)
{
//parent下移
child = parent * 2;
if (child != h->size&&h->data[child] > h->data[child + 1])
child++;//选择更小的上滤
if (x <= h->data[child]) break;
else
h->data[parent] = h->data[child];
}
h->data[parent] = x;
return h;
}
minheap buildHeap(minheap h)
{
int i;
for (i = h->size / 2; i > 0; i--)
h=PercDown(h, i);
return h;
}
int main()
{
int n, m;
minheap h = CreateHeap();
scanf("%d %d", &n, &m);
int i,val;
for (i = 1; i <= n; i++)
{
scanf("%d", &h->data[i]);
h->size++;
}
/*for (i = 1; i <= h->size; i++)
printf("%d ", h->data[i]);
printf("\n\n");*/
h=buildHeap(h);
/*for (i = 1; i <= h->size; i++)
printf("%d ", h->data[i]);
printf("\n\n");*/
for (i = 0; i < m; i++)
{
scanf("%d", &val);
printPath(h, val);
}
return 0;
}