堆的基本操作和堆排序(C语言版)


Heap.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <malloc.h>
#include <string.h>

typedef int DataType;
typedef int (*Compare)(DataType left,DataType right);//函数指针

typedef struct Heap
{
	DataType* _array;//数组指针
	int _capacity;//数组容量
	int _size;//元素个数
	Compare _com;
}Heap;

//交换函数
void Swap(DataType *left,DataType *right);

//向下调整
void AdjustDown(Heap* hp,int parent);

//向上调整
void AdjustUp(Heap* hp,int child);

//创建堆
void Create(Heap* hp,DataType* array,int size,Compare com);

//初始化堆
void HeapInit(Heap* hp,Compare com);

//堆中插入元素
void HeapInsert(Heap* hp,DataType data);

//判空
int HeapEmpty(Heap* hp);

//销毁堆
void DestoryHeap(Heap* hp);

//扩容
void CheckCapacity(Heap* hp);

//堆的元素个数
int HeapSize(Heap* hp);

//获取堆顶元素
DataType HeapTop(Heap* hp);

//小堆规则
int Less(DataType left,DataType right);

//大堆规则
int Greater(DataType left,DataType right);


//堆排序
void HeapSort(int* array,int size);
void AdjustHeap(int* array,int size,int parent);
void SwapSort(int* left,int* right);
void HeapSortPrint(int* array,int size);

Heap.c

#include "Heap.h"

//交换函数
void Swap(DataType *left,DataType *right)
{
	DataType tmp;
	tmp = *left;
	*left = *right;
	*right = tmp;
}

//向下调整
void AdjustDown(Heap* hp,int parent)
{
	int child = parent*2+1;
	assert(hp);
	//默认情况选孩子为左孩子
	while(child < hp->_size)
	{
		//如果右孩子存在且右孩子小于左孩子,那么此时就需要重新标记child为右孩子
		if((child+1) < hp->_size && hp->_array[child] > hp->_array[child+1])
			child += 1;
		if(hp->_array[parent] > hp->_array[child])
		{
			Swap(&hp->_array[child],& hp->_array[parent]);
			parent = child;
			child = parent*2+1;
		}
		else
			return;

	}

}

//向上调整
void AdjustUp(Heap* hp,int child)
{
	int parent = (child-1)>>1;

	if(NULL == hp)
		return;

	if(hp->_array[child] < hp->_array[parent])
	{
		Swap(&hp->_array[child],&hp->_array[parent]);
		child = parent;
		parent = (child -1)>>1;
	}
	else
		return;
}

//创建堆
void Create(Heap* hp,DataType* array,int size,Compare com)
{
	int i = 0;
	int root = 0;
	assert(hp);

	//1.申请空间
	hp->_array = (DataType*)malloc(sizeof(DataType)*size+3);
	hp->_capacity = size+3;
	//2.放置元素
	for( ; i< size;i++)
	{
		hp->_array[i] = array[i];
		hp->_size++;
	}
	hp->_size = size;
	hp->_com = com;
	//3.调整,找叶子节点
	root = (size-2) >> 1;
	for( ; root>=0;root--)
		AdjustDown(hp,root);
}

//初始化堆
void HeapInit(Heap* hp,Compare com)
{
	assert(hp);
	//假设现默认其初始空间申请为3个
	hp->_array = (DataType*)malloc(sizeof(DataType)*3);
	if(NULL == hp)
	{
		printf("申请空间失败!!!\n");
		return;
	}
	hp->_capacity = 3;
	hp->_size = 0;
	hp->_com = com;
}

//堆中插入元素(进行向上调整)
void HeapInsert(Heap* hp,DataType data)
{
	assert(hp);

	CheckCapacity(hp);
	hp->_array[hp->_size++] = data;

	if(hp->_size > 1)
		AdjustUp(hp,hp->_size-1);
}


//判空
int HeapEmpty(Heap* hp)
{
	assert(hp);
	return 0 == hp->_size;
}

//删除堆,每次删除删除堆顶元素
void DestoryHeap(Heap* hp)
{
	assert(hp);
	if(HeapEmpty(hp))
		return;
	//1.将堆中最后一个元素替代堆顶元素
	Swap(&hp->_array[0],&hp->_array[hp->_size-1]);
	//2.将堆中元素个数减少一个,即删除堆中最后一个元素
	hp->_size--;
	//3.堆中结构可能被破坏,再向下调整使其满足对的性质
	AdjustDown(hp,0);
}

//扩容
void CheckCapacity(Heap* hp)
{
	//realloc做的三件事情
	//1.申请新空间
	//2.将旧空间的元素搬移到新空间
	//3.释放旧空间
	if(hp->_size = hp->_capacity)
	{
		int pNewCapacity = (hp->_capacity)*2;
		DataType* newarray = (DataType*)realloc(hp->_array,sizeof(DataType)*pNewCapacity);
		if(NULL == newarray)
		{
			printf("扩容失败!!!\n");
			return;
		}
		free(hp->_array);
		hp->_array = newarray;
		hp->_capacity = pNewCapacity;
	}
}

//堆的元素个数
int HeapSize(Heap* hp)
{
	return hp->_size;
}

//获取堆顶元素
DataType HeapTop(Heap* hp)
{
	assert(hp);
	if(HeapEmpty(hp))
		return -1;
	return hp->_array[0];
}

//小堆规则
int Less(DataType left,DataType right)
{
	return left < right;
}

//大堆规则
int Greater(DataType left,DataType right)
{
	return left > right;
}





//堆排序(此处选择降序排序,用小堆)
void HeapSort(int* array,int size)
{
	//1.向下调整,将树变为小堆
	int root = (size-2)>>2;//找到叶子结点的根
	int end = size-1;//找到最后一个叶子结点
	while(root>=0)
	{
		AdjustHeap(array,size,root);//将树调整为小堆,找到的堆顶元素是最小的
		root--;
	}
	while(end > 0)
	{
		SwapSort(&array[0],&array[end]);//将堆顶元素和最后一个结点的元素交换
		AdjustHeap(array,end,0);//若交换后不满足小堆结构就进行堆调整
		end--;//记得每次调整都要减去1,调整的时候不需要在计入已排序的元素个数
	}
}
void AdjustHeap(int* array,int size,int parent)
{
	int child = parent*2+1;
	while(child < size)
	{
		if( (child+1)<size && array[child] > array[child+1] )
			child += 1;
		if( array[child] < array[parent] )
		{
			SwapSort(&array[child],&array[parent]);
			child = parent;
			parent = (child-1)>>1;
		}
		else
			return;
	}

}
void SwapSort(int* left,int* right)
{
	int tmp;
	tmp = *left;
	*left = *right;
	*right = tmp;
}

void HeapSortPrint(int* array,int size)
{
	int i = 0;
	for( ; i<size;i++)
	{
		printf("%d ",array[i]);
	}
	printf("\n");
}

test.c

#include "Heap.h"

#if 0
int main()
{
	Heap hp;
	int arr[] = {53,17,78,9,45,65,87,23,31};
	HeapInit(&hp,Less);
	Create(&hp,arr,sizeof(arr)/sizeof(arr[0]),Less);
	printf("top is:%d\n",HeapTop(&hp));
	printf("size is:%d\n",HeapSize(&hp));

	DestoryHeap(&hp);
	printf("top is:%d\n",HeapTop(&hp));
	printf("size is:%d\n",HeapSize(&hp));
	printf("heap is empty:%d\n",HeapEmpty(&hp));
	return 0;
}
#endif

int main()
{
	int arr[] = {53,17,78,9,45,65,87,23,31};
	int size = sizeof(arr)/sizeof(arr[0]);
	HeapSortPrint(arr,size);
	HeapSort(arr,size);
	HeapSortPrint(arr,size);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ijn842/article/details/80299647