当前位置:   article > 正文

数据结构——堆的C语言代码实现_数据结构堆分配代码

数据结构堆分配代码

系列文章目录

数据结构——顺序表的C语言代码实现
数据结构——八种链表的C语言代码实现
数据结构——栈的C语言代码实现
数据结构——队列的C语言代码实现
数据结构——堆的C语言代码实现



前言

本文主要学习如何实现最大队和最小堆的创建、插入、删除等。

一、堆的概念

堆是考虑特权的数据结构,被称作优先队列

在前面学习队列时,我们曾举例:在银行中排队处理业务,来解释队列“先进先出”的特点。
而在学习堆时,我们可以联想打印店排队:某一个用户需要打印数百页的资料,而排在他后面的顾客只需打印一两页的试题,那么此时店主和前客户一般都会同意优先处理后客户的需求。
堆是特殊的队列,最常用结构是完全二叉树又因为完全二叉树必的节点规律性极强,故常用数组实现堆的存储。
对于下标为i的节点,其父节点下标为i/2,其左右孩子节点下标为2i、2I+1

二、代码实现

1.Heap.h

主要实现创建、插入、删除和打印。最大堆与最小堆的接口函数一致。
注意在用数组存储堆时,我们使用的数组下标是从1开始的,空余的下标0用于存放规定的最大值或者最小值,便于插入时进行操作。
代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#define MAX 10000000
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int DataType;
typedef struct Heap
{
	DataType* arr;
	int size;
	int capacity;
}*Heap;

//创建堆
Heap CreateHeap(int maxsize);

//检测是否已满
bool CheckFull(Heap h);

//检测是否已空
bool CheckEmpty(Heap h);

//插入
void Insert(Heap h, DataType x);

//删除
DataType Delete(Heap h);

//打印
void Print(Heap h);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

2.Heap.c

最大堆与最小堆的接口函数实现大同小异。重点注意实现插入与删除时。使用的过滤方法!

(1)创建堆

因为从下标1开始存储,所以申请空间时,要申请maxsize+1个空间
代码如下:

//创建堆
Heap CreateHeap(int maxsize)
{
	Heap h = (Heap)malloc(sizeof(struct Heap));
	h->arr = (DataType*)malloc(sizeof(DataType) * (maxsize + 1));
	h->capacity = maxsize;
	h->size = 0;
	//数组从下标1开始存放数据,arr[0]存放最大值,
	//便于插入时进行过滤操作
	h->arr[0] = MAX;
	return h;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

(2)检测是否已满

代码如下:

//检测是否已满
bool CheckFull(Heap h)
{
	return h->size == h->capacity;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(3)检测是否已空

代码如下:

//检测是否已空
bool CheckEmpty(Heap h)
{
	return h->size == 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

(4)插入

主要思路:
1、先判断数组是否已满
2、将数组的size加一赋值为i,然后从数组最后一个下标i开始,依次用父节点(下标为2/i)与插入的数X比较大小
3、在最大堆中,如果父节点小于X,则将父节点下移到孩子节点,然后将i迭代,继续上述比较;在最小堆中,如果父节点大于X,则将父节点移到孩子节点,然后将i迭代,继续上述操作;
4、最终当判断条件结果为假时,X就找到了要插入的位置下标。
代码如下:

//最大堆插入
void Insert(Heap h, DataType x)
{
	if (CheckFull(h))
	{
		printf("最大堆已满!\n");
		return;
	}
	else
	{
		//最大堆插入元素后,最后的数据位置下标
		int i = ++h->size;
		//从最后一个位置向上过滤父节点
		//如果X大于父节点,则父节点下移
		for (; h->arr[i / 2] < x; i /= 2)
		{
			h->arr[i] = h->arr[i / 2];
		}
		//当X小于父节点,此时i就是要插入的位置
		h->arr[i] = x;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
//最小堆的插入
void Insert(Heap h, DataType x)
{
	if (CheckFull(h))
	{
		printf("\n");
		return;
	}
	else
	{
		int i = ++h->size;
		for (; h->arr[i / 2] > x; i /= 2)
		{
			h->arr[i] = h->arr[i / 2];
		}
		h->arr[i] = x;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

(5)删除

主要思路:
1、先判断数组是否已空;
2、取出最大值或者最小值(下标为1的数组元素);
3、然后删除最后一个元素的空间,将原数组的最后一个元素num从上到下,与兄弟节点中较大的进行比较,找到要插入的位置
即先从下标为1开始,它的两个孩子下标分别为2、3,先找到较大的孩子节点。假设是下标为2,用下标为2的元素与num相比。在最大堆中,如果num小,则将下标为1的元素赋值为下表为2的元素(节点上移),然后迭代继续比较,直到num较大,此时的父节点就是X要插入的位置。而在最小堆中,就是比较的结果恰恰相反。
代码如下:

//最大堆删除
DataType Delete(Heap h)
{
	if (CheckEmpty(h))
	{
		printf("最大堆已空!\n");
		exit(-1);
	}
	else
	{
		//取出最大元素
		int Max = h->arr[1];
		//用最后一个节点元素从上向下过滤
		int num = h->arr[h->size--];
		int parent, child;
		for (parent = 1; 2 * parent <= h->size; parent = child)
		{
			child = parent * 2;
			//找到两个孩子中较大的一个
			if (child != h->size && h->arr[child + 1] > h->arr[child])
				child += 1;
			//最后一个节点大于孩子节点,则找到了正确位置
			//最后一个节点插入到父节点
			if (num >= h->arr[child])
				break;
			else
				h->arr[parent] = h->arr[child];
		}
		h->arr[parent] = num;
		return Max;
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
//最小堆删除
DataType Delete(Heap h)
{
	if (CheckEmpty(h))
	{
		printf("ѿ!\n");
		exit(-1);
	}
	else
	{
		DataType min = h->arr[1];
		DataType num = h->arr[h->size--];
		int parent, child;
		for (parent = 1; parent * 2 <= h->size; parent = child)
		{
			child = parent * 2;
			if (child != h->size && h->arr[child] > h->arr[child + 1])
				child += 1;
			if (h->arr[child] >= num)
				break;
			else
				h->arr[parent] = h->arr[child];
		}
		h->arr[parent] = num;
		return min;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

(6)打印

代买如下:

//打印
void Print(Heap h)
{
	int i = 1;
	for (; i <= h->size; i++)
	{
		printf("%d ", h->arr[i]);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3.test.c

最大堆:

#include"MaxHeap.h"
int main()
{
	int maxsize = 100;
	Heap h = CreateMaxHeap(maxsize);
	int input = 0;
	int count = 0;
	while ((scanf("%d", &input) == 1)&&count<=maxsize)
	{
		Insert(h, input);
		count++;
	}
	printf("最大堆为:\n");
	Print(h);
	int max = Delete(h);
	printf("\n最大值是:%d\n", max);
	printf("最大堆为:\n");
	Print(h);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

最小堆:

#include"Heap.h"
int main()
{
	int maxsize = 100;
	Heap h = CreateHeap(maxsize);
	int count = 0;
	int input = 0;
	while (scanf("%d", &input) == 1 && count <= maxsize)
	{
		Insert(h, input);
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("最小堆是:\n");
		Print(h);
		int min = Delete(h);
		printf("\n最小值是:%d\n", min);
		printf("最小堆是:\n");
		Print(h);
	}
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

总结

多分析代码,理解逐层过滤的方便之处。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/453629
推荐阅读
相关标签
  

闽ICP备14008679号