109人参与 • 2024-08-06 • 数据结构
目录
下面我们来看一个树的结构图:
从上图可以看出:
堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆(例如下面第一张图所示);或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆(例如下面第二张图所示)
typedef int hpdatatype;
typedef struct heap
{
hpdatatype* a;//数组
int size;//堆结点个数
int capacity;//堆的容量
}heap;
// 堆的构建
void heapcreate(heap* hp)
{
assert(hp);
hp->a = (hpdatatype*)malloc(sizeof(int) * 4);
hp->size = 0;
hp->capacity = 4;
}
//堆的向上调整
void adjustup(hpdatatype* a, int child)
{
//这里构建的是大根堆
int parent = (child - 1) / 2;
while (child > 0)//如果孩子结点不大于0就跳出循环
{
if (a[child] > a[parent])
{
swap(&a[child], &a[parent]);
child = parent;//孩子结点走到父节点
parent = (child - 1) / 2;//更新父节点
}
else
{
break;
}
}
}
void heappush(heap* hp, hpdatatype x)
{
assert(hp);
if (hp->size == hp->capacity)//判断堆的容量是否满足
{
hpdatatype* tmp = (hpdatatype*)realloc(hp->a, sizeof(int) * hp->capacity * 2);
if (tmp == null)
{
perror("realloc fail:");
exit(-1);
}
hp->a = tmp;
hp->capacity *= 2;
}
hp->a[hp->size] = x;
hp->size++;
adjustup(hp->a, hp->size - 1);//插入向上调整算法
}
//堆的向下调整
void adjustdown(hpdatatype* a, int n, int parent)
{
int child = 2 * parent + 1;
while (child < n)
{
if (child + 1 < n && a[child + 1] > a[child])
{
child += 1;
}
if (a[child] > a[parent])
{
swap(&a[child], &a[parent]);
parent = child;
child = 2 * parent + 1;
}
else
{
break;
}
}
}
void heappop(heap* hp)
{
assert(hp);
swap(&hp->a[0], &hp->a[hp->size - 1]);将堆顶的数和最后一个叶子结点交换
hp->size--;//堆个数减1
adjustdown(hp->a, hp->size, 0);//调用向下调整算法
}
hpdatatype heaptop(heap* hp)
{
assert(hp);
return hp->a[0];
}
int heapsize(heap* hp)
{
assert(hp);
return hp->size;
}
bool heapempty(heap* hp)
{
assert(hp);
return hp->size == 0;
}
void heapdestory(heap* hp)
{
assert(hp);
free(hp->a);
hp->capacity = hp->size = 0;
}
时间复杂度证明如下图所示:
计算证明如下图所示:
堆排序就是利用堆进行排序的方法。它的基本思想是,将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根节点。将它移走(其实就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值),然后将剩余的n-1个序列重新构造一个堆,这就会得到n个元素的次大值。如此反复执行,便能得到一个有序序列。
堆排序的图形演示:
#define _crt_secure_no_warnings 1
#include<stdio.h>
void swap(int* p1, int* p2)
{
int x = *p1;
*p1 = *p2;
*p2 = x;
}
void printarray(int* a, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
}
void adjustdown(int* a, int n, int parent)
{
int child = 2 * parent + 1;
while (child <= n)
{
if (child + 1 <= n && a[child + 1] < a[child])
{
child += 1;
}
if (a[child] < a[parent])
{
swap(&a[child], &a[parent]);
parent = child;
child = 2 * parent + 1;
}
else
{
break;
}
}
}
void heapsort(int* a, int n)
{
for (int i = (n - 2) / 2; i >= 0; i--)
{
adjustdown(a, n - 1, i);
}
int end = n - 1;
while (end > 0)
{
swap(&a[0], &a[end]);
end--;
adjustdown(a, end, 0);
}
printarray(a, n);
}
int main()
{
int a[10] = { 4,2,7,8,3,1,5,6,9,0 };
heapsort(a, sizeof(a) / sizeof(a[0]));
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<time.h>
void swap(int * p1,int * p2)
{
int x = *p1;
*p1 = *p2;
*p2 = x;
}
//堆的向下调整
void adjustdown(int * a, int n, int parent)
{
int child = 2 * parent + 1;
while (child < n)
{
if (child + 1 < n && a[child + 1] < a[child])
{
child += 1;
}
if (a[child] < a[parent])
{
swap(&a[child], &a[parent]);
parent = child;
child = 2 * parent + 1;
}
else
{
break;
}
}
}
void printtopk(const char* fin, int k)
{
// 1. 建堆--用a中前k个元素建堆
int* topk = (int*)malloc(sizeof(int) * k);
if (topk == null)
{
perror("malloc fail:");
return;
}
file* fout = fopen(fin, "r");
if (fout == null)
{
perror("file fail");
return;
}
for (int i = 0; i < k; i++)
{
fscanf(fout,"%d",&topk[i]);
}
// 2. 将剩余n-k个元素依次与堆顶元素交换,不满则则替换
for (int i = (k - 2) / 2; i >= 0; i--)
{
adjustdown(topk, k, i);
}
int val = 0;
int ret = fscanf(fout, "%d", &val);
while (ret != eof)
{
if (val > topk[0])
{
topk[0] = val;
adjustdown(topk, k, 0);
}
ret = fscanf(fout, "%d", &val);
}
for (int i = 0; i < k; i++)
{
printf("%d ", topk[i]);
}
printf("\n");
free(topk);
fclose(fout);
}
void createndate()
{
// 造数据
int n = 10000;
srand(time(0));
const char* file = "data.txt";
file* fin = fopen(file, "w");
if (fin == null)
{
perror("fopen error");
return;
}
for (size_t i = 0; i < n; ++i)
{
int x = rand() % 10000;
fprintf(fin, "%d\n", x);
}
fclose(fin);
}
int main()
{
createndate();
printtopk("data.txt", 10);
return 0;
}
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论