堆操作

本文深入探讨了堆数据结构的原理与应用,详细讲解了堆的初始化、销毁、插入、删除、排序等核心操作,并提供了完整的C语言实现代码。通过实例演示了堆的创建、调整、打印及排序过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

头文件heap.h

#ifndef _HEAP_H_
#define _HEAP_H_
typedef int HPDataType;

typedef struct Heap
{
	HPDataType* data;
	int size;
	int capacity;
}Heap;

void adjustDown(Heap* hp, int n);  //向下排序
void HeapInit(Heap* hp, HPDataType* a, int n); //数组转换成堆
void HeapDestory(Heap* hp);  //销毁
void HeapPush(Heap* hp, HPDataType x);  //插入
void HeapPop(Heap* hp);   //删除堆顶元素
HPDataType HeapTop(Heap* hp);  //输出堆顶元素
int HeapSize(Heap* hp);   //大小
void HeapPrint(Heap* hp);   //打印
int HeapEmpty(Heap* hp);  //返回堆是否为空
void HeapSort(Heap* hp);  //堆排序

#endif /*_HEAP_H_ */

函数实现文件heap.c

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

void adjustDown(Heap* hp, int m) //向下排序算法,n为下标   大堆
{
	int cur = m;
	int n;
	while (cur * 2 + 1 < hp->size) //无左孩子则不进入循环
	{
		if (cur * 2 + 2 >= hp -> size)  //无右孩子,则直接和左孩子交换
		{
			n = cur * 2 + 1;  
		}
		else  
		{
			if (hp->data[cur * 2 + 1] > hp->data[cur * 2 + 2]) //左右孩子比较大小
			{
				n = cur * 2 + 1;  //大堆,左右孩子中谁大和谁换
			}
			else
			{
				n = cur * 2 + 2;
			}
		}
		if (hp->data[cur] < hp->data[n])  //和挑出较大的孩子比较,看是否需要交换
		{
			int tmp = hp->data[cur];
			hp->data[cur] = hp->data[n];
			hp->data[n] = tmp;
			cur = n;
		}
		else
		{
			break;
		}
	}
}

void HeapInit(Heap* hp, HPDataType* a, int n) // 初始化, n即为数组长度
{
	hp->capacity = n * 2; //容量为数组长度的2倍
	hp->size = n;
	hp->data = (HPDataType *)calloc(hp->capacity, sizeof(HPDataType));

	for (int i = 0; i < n; i++)
	{
		hp->data[i] = a[i]; //把数组拷贝到堆中
	}
	for(int i = n / 2 - 1; i > 0; i--)
	{
		adjustDown(hp, i); //向下调整算法,使数组变为堆,后才能进行堆排序操作
	}
}

void HeapDestory(Heap* hp)  //销毁
{
	if (hp->data)  //释放前先判空
	{
		free(hp->data);
	}
		hp->data = NULL;
		hp->capacity = 0;
		hp->size = 0;
}

void HeapPrint(Heap* hp)  //打印
{
	int i;
    int rn = 0;
    int bin = 1;
    for (i = 0; i < hp->size; ++i)  
    {
    	printf("%d ", hp->data[i]);
    	if (i == rn)   //按层打印
    	{
    		putchar('\n');
    		bin *= 2;
			rn += bin;
    	}
    }
	printf("\n\n");
}  

void HeapPush(Heap* hp, HPDataType x) //插入新数,向上调整算法,和父节点比较
{
	if (hp->size == hp->capacity)  //判断容量是否够用,不够则扩容
	{
		hp->capacity *= 2;
		hp->data = (HPDataType *)realloc(hp->data, hp->size, sizeof(HPDataType));
	}
	int cur = hp->size;  //要调整的下标
	hp->data[cur] = x;
	hp->size++;
	while (hp->data[(cur - 1) / 2])  //父节点存在则执行循环
	{
		if (hp->data[cur] > hp->data[(cur - 1) / 2]) //和父节点比较,判断是否要交换
		{
			int tmp = hp->data[cur];
			hp->data[cur] = hp->data[(cur - 1) / 2];
			hp->data[(cur - 1) / 2] = tmp;
			cur = (cur - 1) / 2;
		}
		else
			break;
	}

}

void HeapPop(Heap* hp)
{
	if (hp->size == 0)  //判空
	{
		return;
	}
	hp->size--;
	int tmp;
	//hp->data[0] = hp->data[hp->size];
	tmp = hp->data[0];   //堆顶元素与最后一个元素交换
	hp->data[0] = hp->data[hp->size];
	hp->data[hp->size] = tmp;
	 
	adjustDown(hp, 0);  //把交换过后的堆顶元素向下排序
}

HPDataType HeapTop(Heap* hp)  //返回堆顶元素
{
	if (hp->size == 0)
	{
		return (HPDataType)0; //强制类型转换
	}
	return hp->data[0];
}

void HeapSort(Heap* hp) //堆排序
{
	int tmp = hp->size;
	while (hp->size > 1)
	{
		HeapPop(hp);
	}
	hp->size = tmp;
}

int HeapSize(Heap* hp)
{
	return hp->size;
}

int HeapEmpty(Heap* hp)
{
	return hp->size == 0;  //为空
}

void adjustDown(Heap* hp, int n);
void HeapInit(Heap* hp, HPDataType* a, int n);
void HeapDestory(Heap* hp);
void HeapPush(Heap* hp, HPDataType x);
void HeapPop(Heap* hp);
HPDataType HeapTop(Heap* hp); //返回最顶端的值
int HeapSize(Heap* hp);
int HeapEmpty(Heap* hp);
void HeapSort(Heap* hp);
void HeapPrint(Heap* hp);

主函数main.c

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


int main()
{
	int a;
	int data[10] = { 29,48,72,53,45,30,18,36,13,35 };
	Heap hp;
	HeapInit(&hp, data, 10);
	HeapPrint(&hp);
    
	adjustDown(&hp, 1);
	HeapPrint(&hp);
	
	HeapPush(&hp, 49);
	HeapPrint(&hp);
	
	HeapPop(&hp);
	HeapPrint(&hp);
	
	HeapSort(&hp);
	HeapPrint(&hp);
	a =  HeapTop(&hp); //返回最顶端的值
	printf("%d", a);
	HeapDestory(&hp);
	HeapPrint(&hp);
	
	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值