堆的向下调整算法,堆的基本操作和堆排序(堆的概念,结构和堆排序思想)

堆的向下调整算法,堆的基本操作和堆排序

1、堆的概念

堆是一颗完全二叉树,它是由一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

堆的两个特点:
1、堆的某个节点的值总是不大于或者不小于其父节点的值
2、堆是一颗完全二叉树

2、堆的结构

现实中我们通常把堆用一个动态开辟的数组来实现

typedef int HeapDataType;

typedef struct Heap
{
	HeapDataType *_array;
	size_t _size;
	size_t _capacity;
}Heap;

3、堆的基本操作

3.1、堆的向下调整算法

左右子树都是堆的前提下,可以采用向下调整算法对根节点实行向下调整算法,可以把堆调整成一个小堆。

算法过程;

1、判断根节点的左孩子是否存在;
2、若是存在则判断右孩子是否存在,左右孩子的大小
3、将较小孩子的节点赋值给min
4、比较最小节点和父节点的大小,将较小的节点的小标赋值给父节点

算法实现:

//向下调整算法
void HeapAdjustdown(Heap *pheap, int root)
{
	assert(pheap);

	while (2 * root + 1 < pheap->_size)
	{
		int min;
		int left = 2 * root + 1;
		int right = 2 * root + 2;
		if (right >= pheap->_size)
		{
			min = left;
		}
		else
		{
			if (pheap->_array[left] > pheap->_array[right])
			{
				min = left;
			}
			else
			{
				min = right;
			}
		}	
		if (pheap->_array[root] < pheap->_array[min])
		{
			HeapDataType tmp = pheap->_array[root];
			pheap->_array[root] = pheap->_array[min];
			pheap->_array[min] = tmp;
			root = min;
		}
		else
		{
			break;
		}
	}
}

3.2、堆的创建

给出一个数组,将数组元素赋值给堆的数组,再对非叶子节点从后向前执行向下调整算法

堆的创建的实现:

扫描二维码关注公众号,回复: 11122927 查看本文章
//初始化
void HeapInit(Heap *pheap, HeapDataType *arr, size_t capacity)
{
	assert(pheap);
	pheap->_capacity = capacity * 2;
	pheap->_size = capacity;
	pheap->_array = (HeapDataType *)malloc(pheap->_capacity*sizeof(HeapDataType));
	assert(pheap->_array);
	for (int i = 0; i < pheap->_size; i++)
	{
		pheap->_array[i] = arr[i];
	}
	for (int i = (pheap->_size / 2) - 1; i >= 0; i--)
	{
		HeapAdjustdown(pheap, i);
	}
}

3.3、堆的插入

在最后一个元素插入元素,堆的大小加一,然后再对非叶子节点从后向前执行向下调整算法

堆的插入的实现:

//插入
void HeapPush(Heap *pheap, HeapDataType x)
{
	assert(pheap);
	CheckCapacity(pheap);
	pheap->_array[pheap->_size] = x;
	pheap->_size++;
	for (int i = (pheap->_size / 2) - 1; i >= 0; i--)
	{
		HeapAdjustdown(pheap, i);
	}
}

3.4、堆的删除

堆的删除是堆顶元素和堆的最后一个元素交换,删除新的堆顶元素,堆的大小减一,再对非叶子节点从后向前执行向下调整算法

堆的删除实现:

//删除
void HeapPop(Heap *pheap)
{
	assert(pheap);
	HeapDataType tmp = pheap->_array[0];
	pheap->_array[0] = pheap->_array[pheap->_size - 1];
	pheap->_array[pheap->_size - 1] = tmp;
	pheap->_size--;
	for (int i = (pheap->_size / 2) - 1; i >= 0; i--)
	{
		HeapAdjustdown(pheap, i);
	}
}

4、堆排序的思想

堆排序的思想是,实现堆的堆顶元素和堆的最后一个元素交换,再执行非叶子节点从后向前的向下调整算法,知道堆顶元素和第二个元素交换完成并实现向下调整算法为止,最终实现堆排序

堆排序的实现:

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

5、堆的实现

Heap.h

#ifndef _HEAP_H_
#define _HEAP_H_

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>

#define CAPACITY 2
#define ARRSIZE 11

typedef int HeapDataType;

typedef struct Heap
{
	HeapDataType *_array;
	size_t _size;
	size_t _capacity;
}Heap;


//向下调整算法
void HeapAdjustdown(Heap *pheap, int root);
//初始化
void HeapInit(Heap *pheap, HeapDataType *arr, size_t capacity);
//销毁
void HeapDestory(Heap *pheap);
//开辟空间
void CheckCapacity(Heap *pheap);
//插入
void HeapPush(Heap *pheap, HeapDataType x);
//删除
void HeapPop(Heap *pheap);
//返回堆顶元素
HeapDataType HeapTop(Heap *pheap);
//返回堆的大小
int HeapSize(Heap *pheap);
//判空
int HeapEmpty(Heap *pheap);
//打印堆
void HeapPrint(Heap *pheap);
//堆排序
void HeapSort(Heap *pheap);

#endif //_HEAP_H_

Heap.c

#include	 "Heap.h"

//向下调整算法
void HeapAdjustdown(Heap *pheap, int root)
{
	assert(pheap);

	while (2 * root + 1 < pheap->_size)
	{
		int min;
		int left = 2 * root + 1;
		int right = 2 * root + 2;
		if (right >= pheap->_size)
		{
			min = left;
		}
		else
		{
			if (pheap->_array[left] > pheap->_array[right])
			{
				min = left;
			}
			else
			{
				min = right;
			}
		}	
		if (pheap->_array[root] < pheap->_array[min])
		{
			HeapDataType tmp = pheap->_array[root];
			pheap->_array[root] = pheap->_array[min];
			pheap->_array[min] = tmp;
			root = min;
		}
		else
		{
			break;
		}
	}
}

//初始化
void HeapInit(Heap *pheap, HeapDataType *arr, size_t capacity)
{
	assert(pheap);
	pheap->_capacity = capacity * 2;
	pheap->_size = capacity;
	pheap->_array = (HeapDataType *)malloc(pheap->_capacity*sizeof(HeapDataType));
	assert(pheap->_array);
	for (int i = 0; i < pheap->_size; i++)
	{
		pheap->_array[i] = arr[i];
	}
	for (int i = (pheap->_size / 2) - 1; i >= 0; i--)
	{
		HeapAdjustdown(pheap, i);
	}
}

//销毁
void HeapDestory(Heap *pheap)
{
	assert(pheap);
	if (pheap->_array)
	{
		free(pheap->_array);
	}
	pheap->_array = NULL;
	pheap->_size = 0;
	pheap->_capacity = 0;
}

//开辟空间
void CheckCapacity(Heap *pheap)
{
	assert(pheap);
	if (pheap->_size == pheap->_capacity)
	{
		pheap->_capacity *= CAPACITY;
		pheap->_array = (HeapDataType *)realloc(pheap->_array, pheap->_capacity*sizeof(HeapDataType));
	}
}

//插入
void HeapPush(Heap *pheap, HeapDataType x)
{
	assert(pheap);
	CheckCapacity(pheap);
	pheap->_array[pheap->_size] = x;
	pheap->_size++;
	for (int i = (pheap->_size / 2) - 1; i >= 0; i--)
	{
		HeapAdjustdown(pheap, i);
	}
}

//删除
void HeapPop(Heap *pheap)
{
	assert(pheap);
	HeapDataType tmp = pheap->_array[0];
	pheap->_array[0] = pheap->_array[pheap->_size - 1];
	pheap->_array[pheap->_size - 1] = tmp;
	pheap->_size--;
	for (int i = (pheap->_size / 2) - 1; i >= 0; i--)
	{
		HeapAdjustdown(pheap, i);
	}
}

//返回堆顶元素
HeapDataType HeapTop(Heap *pheap)
{
	assert(pheap);
	return pheap->_array[0];
}

//返回堆的大小
int HeapSize(Heap *pheap)
{
	assert(pheap);
	return pheap->_size;
}

//判空
int HeapEmpty(Heap *pheap)
{
	assert(pheap);
	return (pheap->_size > 0) ? -1 : 1;
}

//打印堆
void HeapPrint(Heap *pheap)
{
	assert(pheap);
	int count = 0;
	for (int i = 0; i < (int)log2(pheap->_size); i++)
	{
		printf("\n");
		for (int j = pow(2, i) - 1; j < pow(2, i + 1) - 1; j++)
		{
			printf(" %d ", pheap->_array[j]);
			count++;
		}
	}
	for (int k = count; k < pheap->_size; k++)
	{
		printf("%d ", pheap->_array[k]);
	}
	printf("\n");
}

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

main.c

#include "Heap.h"

int main()
{
	Heap heap;
	HeapDataType arr[ARRSIZE] = { 11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	HeapInit(&heap, arr, ARRSIZE);
	HeapPrint(&heap);
	HeapPush(&heap, 12);
	HeapPush(&heap, 13);
	HeapPush(&heap, 14);
	HeapPush(&heap, 15);
	HeapPush(&heap, 16);
	HeapPush(&heap, 17);
	HeapPush(&heap, 18);
	HeapPush(&heap, 19);
	HeapPrint(&heap);

	HeapPop(&heap);
	HeapPrint(&heap);

	printf("HeapDataType = %d \n", HeapTop(&heap));
	printf("HeapSize = %d \n", HeapSize(&heap));
	printf("HeapEmpty = %d \n", HeapEmpty(&heap));

	HeapSort(&heap);
	HeapPrint(&heap);
	HeapDestory(&heap);
	system("pause");
	return 0;
}
发布了117 篇原创文章 · 获赞 48 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/gp1330782530/article/details/104774605
今日推荐