//Heap.h文件
#include
#include
#include
#include
typedef int HPDataType;
typedef struct HeapNode
{
HPDataType* data;
int size;
int capacity;
}HP;
//初始化
void HeapInit(HP* php);
//销毁
void HeapDestory(HP* php);
//插入
void HeapPush(HP* php, HPDataType x);
//删除
void HeapPop(HP* php);
//返回堆顶的数据
HPDataType HeapTop(HP* php);
//返回堆的大小
int HeapSize(HP* php);
//判空
bool HeapEmpty(HP* php);
//向上调整
void AdjustUp(HPDataType* data, int child);
//向下调整
void AdjustDown(HPDataType* data, int n, int parent);
//交换
void Swap(HPDataType* v1, HPDataType* v2);
//Heap.c文件
#include "Heap.h"
void HeapInit(HP* php)
{
assert(php);
php->data = NULL;
php->size = 0;
php->capacity = 0;
}
void HeapDestory(HP* php)
{
assert(php);
free(php->data);
php->data = NULL;
php->size = 0;
php->capacity = 0;
}
void Swap(HPDataType* v1, HPDataType* v2)
{
HPDataType tmp = *v1;
*v1 = *v2;
*v2 = tmp;
}
void AdjustUp(HPDataType* data, int child)
{
assert(data);
int parent = (child - 1) / 2;
while (child > 0)
{
//按小堆来,如果双亲大于孩子,就交换
if (data[parent] > data[child])
{
/*HPDataType tmp = data[parent];
data[parent] = data[child];
data[child] = tmp;*/
Swap(&data[parent], &data[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void HeapPush(HP* php, HPDataType x)
{
assert(php);
//扩容
if (php->size == php->capacity)
{
int newCapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
HPDataType* tmp = (HPDataType*)realloc(php->data, sizeof(HPDataType) * newCapacity);
if (tmp == NULL)
{
perror("realloc fail!\n");
return;
}
php->data = tmp;
php->capacity = newCapacity;
}
php->data[php->size] = x;
php->size++;
//向上调整
AdjustUp(php->data, php->size - 1);
}
void AdjustDown(HPDataType* data, int n, int parent)
{
int child = parent * 2 + 1;
while (child < n)
{
if (child + 1 < n && data[child + 1] < data[child])
{
child++;
}
if (data[child] < data[parent])
{
Swap(&data[child], &data[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
//删除堆顶的数据
void HeapPop(HP* php)
{
assert(php);
assert(!HeapEmpty(php));
//第一个和最后一个交换
Swap(&php->data[0], &php->data[php->size - 1]);
php->size--;
//向下调整
AdjustDown(php->data, php->size, 0);
}
HPDataType HeapTop(HP* php)
{
assert(php);
assert(!HeapEmpty(php));
return php->data[0];
}
int HeapSize(HP* php)
{
assert(php);
return php->size;
}
bool HeapEmpty(HP* php)
{
assert(php);
return php->size == 0;
}
给一个数组进行排序,首先应该先建一个堆,排升序建大堆,排降序建小堆,创建好堆后,将堆顶元素和最后一个元素交换,这样就把最大的或最小的数放在了最后。再把除了最后一个数之外的数据向下调整建堆,再交换,这就就把次大的或次小的数放在了倒数第二个位置。循环这个过程,这个数组中的数据就会按降序或升序变得有序。
代码如下(按降序实现):
#include
void Swap(int* v1, int* v2)
{
int tmp = *v1;
*v1 = *v2;
*v2 = tmp;
}
void AdjustDown(int* arr, int n, int parent)
{
int child = parent * 2 + 1;
while (child < n)
{
if (child + 1 < n && arr[child + 1] < arr[child])
{
child++;
}
if (arr[child] < arr[parent])
{
Swap(&arr[child], &arr[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(int* arr, int n)
{
//建堆
//升序——建大堆
//降序——建小堆
//向下调整建堆
for (int i = (n - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(arr, n, i);
}
int end = n - 1;
while (end > 0)
{
//交换
Swap(&arr[0], &arr[end]);
//向下调整
AdjustDown(arr, end, 0);
end--;
}
}
int main()
{
int arr[] = { 2,5,6,1,4,7,0,9,8,3 };
int sz = sizeof(arr) / sizeof(arr[0]);
HeapSort(arr, sz);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
运行结果:
堆排序的时间复杂度:O(N*log₂N)
代码实现:
#include
#include
#include
void AdjustDown(int* a, int n, int parent)
{
int child = parent * 2 + 1;
while (child < n)
{
if (child + 1 < n && a[child + 1] < a[child])
{
child++;
}
if (a[child] < a[parent])
{
int tmp = a[child];
a[child] = a[parent];
a[parent] = tmp;
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void CreateData()
{
FILE* fin = fopen("data.txt", "w");
if (fin == NULL)
{
perror("fopen fail\n");
return;
}
int n = 1000;
srand(time(0));
for (int i = 0; i < n; i++)
{
int x = rand() % 1000000;
fprintf(fin, "%d\n", x);
}
fclose(fin);
}
void PrintTopK(int k)
{
FILE* fout = fopen("data.txt", "r");
if (fout == NULL)
{
perror("fopen fail\n");
return;
}
int* a = (int*)malloc(sizeof(int) * k);
if (a == NULL)
{
perror("malloc fail\n");
return;
}
for (int i = 0; i < k; i++)
{
fscanf(fout, "%d", &a[i]);
}
//建小堆——向下调整
for (int i = (k - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(a, k, i);
}
while (!feof(fout))
{
int x = 0;
fscanf(fout, "%d", &x);
if (a[0] < x)
{
a[0] = x;
AdjustDown(a, k, 0);
}
}
//排序
int end = k - 1;
while (end > 0)
{
int tmp = a[0];
a[0] = a[end];
a[end] = tmp;
AdjustDown(a, end, 0);
end--;
}
for (int i = 0; i < k; i++)
{
printf("%d ", a[i]);
}
printf("\n");
fclose(fout);
}
int main()
{
CreateData();
PrintTopK(5);
return 0;
}
运行结果: