大根堆-小根堆-堆排序-C实现

大根堆小根堆的实现:以PPT形式呈现大根堆构建的理论过程

1、首先涉及到一个堆的调整,这也是算法的核心部分。假设树中,节点i的子树已经为两个大根堆。这两个子树再加上i节点的话,可能是大根堆也可能不是,因此需要对节点i进行调整。若i小于left(i) or right(i),需要将i下移。

2、这是一个例子,需要将4下移。满足大根堆的性质。

3、大根堆的调整算法。假设i节点的两个子树已经是大根堆。对应代码中MaxHeapify()函数。

4、算法正确性分析。

5、构建大根堆的过程中,只需要考虑n/2 + 1 之前的节点,因为之后的节点都是叶节点。

6、构建大根堆的算法。对应代码中MaxHeapCreat()函数


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
/*
目的:建立大根堆,也可以变成小根堆,
核心:堆的调整
输入:一系列来自文件的整数。文件中整数以空格隔开
输出:大根堆
*/


void Swap(uint32_t* array, uint32_t i, uint32_t j)
{
	assert(array);
	uint32_t tmp;
	tmp = array[j];
	array[j] = array[i];
	array[i] = tmp;
}


/*大根堆调整*/
void MaxHeapify(uint32_t* array, uint32_t heapSize, uint32_t currentNode)
{
	uint32_t leftChild, rightChild,  largest;
	leftChild = 2*currentNode + 1;
	rightChild = 2*currentNode + 2;
	if(leftChild < heapSize && array[leftChild] > array[currentNode])
		largest = leftChild;
	else
		largest = currentNode;
	if(rightChild < heapSize && array[rightChild] > array[largest])
		largest = rightChild;
	if(largest != currentNode)
	{
	    Swap(array, largest, currentNode);
		MaxHeapify(array, heapSize, largest);
	}
}


/*构建大根堆*/
void MaxHeapCreat(uint32_t* array, uint32_t heapSize)
{
	int i;
	for(i = heapSize/2; i >= 0; i--)
	{
		MaxHeapify(array, heapSize, i);
	}
}


/*小根堆调整*/
void MinHeapify(uint32_t* array, uint32_t heapSize, uint32_t currentNode)
{
	uint32_t leftChild, rightChild,  minimum;
	leftChild = 2*currentNode + 1;
	rightChild = 2*currentNode + 2;
	if(leftChild < heapSize && array[leftChild] < array[currentNode])
		minimum = leftChild;
	else
		minimum = currentNode;
	if(rightChild < heapSize && array[rightChild] < array[minimum])
		minimum = rightChild;
	if(minimum != currentNode)
	{
	    Swap(array, minimum, currentNode);
		MinHeapify(array, heapSize, minimum);
	}
}
/*构建小根堆*/
void MinHeapCreat(uint32_t* array, uint32_t heapSize)
{
	int i;
	for(i = heapSize/2; i >= 0; i--)
	{
		MinHeapify(array, heapSize, i);
	}
}
int main()
{
	uint32_t tmp;
	uint32_t *array;
	array = malloc(sizeof(uint32_t));
	int i, heapSize = 0;


	/*从文件中读出待排序数据*/
    char* filePathway = "C:/Users/Administrator/Desktop/data.txt";
    FILE* fp;
	fp = fopen(filePathway, "rb");
	if(!fp)
	{
	    fprintf(stderr, "Can not open file correctly\n");
	}
	while(!feof(fp))
	{
	    fscanf(fp, "%d", &tmp);
	    heapSize++;
	    array = realloc(array, sizeof(uint32_t) * (heapSize ));
	    if(array == NULL)
	    {
	        fprintf(stderr, "realloc error!\n");
	        return 1;
	    }
	    array[heapSize - 1] = tmp;
    }
    printf("The origen dataset:\n");
    for(i = 0; i < heapSize; i++)
    {
        printf("%d\t", array[i]);
    }
    printf("\n");


    /*构建小根堆并输出*/
    MinHeapCreat(array, heapSize);
    printf("Output the MinHeap:\n");
    for(i = 0; i < heapSize; i++)
    {
        printf("%d\t", array[i]);
    }
    printf("\n");


    /*构建大根堆并输出*/
    MaxHeapCreat(array, heapSize);
    printf("Output the MaxHeap:\n");
    for(i = 0; i < heapSize; i++)
    {
        printf("%d\t", array[i]);
    }
    free(array);
	fclose(fp);


	return 0;
}



这里再加上一个堆的排序算法

首先看一个例子的演示(图片均来自哈工大李建中《算法设计与分析》课件)

通过这个例子不难看出,主要思想是将大根堆的对顶取出,放到数组的最后一个位置,将最后一个位置原来的数放到堆顶,然后对堆顶做调整Max-Heapify(见链接内博客)。

算法伪代码:

重点来啦,直接上代码,代码亲测没有问题的,只是可能得换一下输入数据而已。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
/*
目的:建立大根堆,也可以变成小根堆,
核心:堆的调整
输入:文件,整数以空格隔开
输出:大根堆
*/


void Swap(uint32_t* array, uint32_t i, uint32_t j)
{
	assert(array);
	uint32_t tmp;
	tmp = array[j];
	array[j] = array[i];
	array[i] = tmp;
}


/*大根堆调整*/
void MaxHeapify(uint32_t* array, uint32_t heapSize, uint32_t currentNode)
{
	uint32_t leftChild, rightChild,  largest;
	leftChild = 2*currentNode + 1;
	rightChild = 2*currentNode + 2;
	if(leftChild < heapSize && array[leftChild] > array[currentNode])
		largest = leftChild;
	else
		largest = currentNode;
	if(rightChild < heapSize && array[rightChild] > array[largest])
		largest = rightChild;
	if(largest != currentNode)
	{
	    Swap(array, largest, currentNode);
		MaxHeapify(array, heapSize, largest);
	}
}


/*构建大根堆*/
void MaxHeapCreat(uint32_t* array, uint32_t heapSize)
{
	int i;
	for(i = heapSize/2; i >= 0; i--)
	{
		MaxHeapify(array, heapSize, i);
	}
}


/*小根堆调整*/
void MinHeapify(uint32_t* array, uint32_t heapSize, uint32_t currentNode)
{
	uint32_t leftChild, rightChild,  minimum;
	leftChild = 2*currentNode + 1;
	rightChild = 2*currentNode + 2;
	if(leftChild < heapSize && array[leftChild] < array[currentNode])
		minimum = leftChild;
	else
		minimum = currentNode;
	if(rightChild < heapSize && array[rightChild] < array[minimum])
		minimum = rightChild;
	if(minimum != currentNode)
	{
	    Swap(array, minimum, currentNode);
		MinHeapify(array, heapSize, minimum);
	}
}
/*构建小根堆*/
void MinHeapCreat(uint32_t* array, uint32_t heapSize)
{
	int i;
	for(i = heapSize/2; i >= 0; i--)
	{
		MinHeapify(array, heapSize, i);
	}
}




void HeapSort(uint32_t* array, uint32_t heapSize)
{
    MaxHeapCreat(array, heapSize);
    int i;
    uint32_t arraySize = heapSize;
    for(i = arraySize - 1; i >= 1; i--)
    {
        Swap(array, 0, i);
        heapSize--;
        MaxHeapify(array, heapSize, 0);
    }
}




int main()
{
	uint32_t tmp;
	uint32_t *array;
	array = malloc(sizeof(uint32_t));
	int i, heapSize = 0;


	/*从文件中读出待排序数据*/
    char* filePathway = "C:/Users/Administrator/Desktop/data.txt";
    FILE* fp;
	fp = fopen(filePathway, "rb");
	if(!fp)
	{
	    fprintf(stderr, "Can not open file correctly\n");
	}
	while(!feof(fp))
	{
	    fscanf(fp, "%d", &tmp);
	    heapSize++;
	    array = realloc(array, sizeof(uint32_t) * (heapSize ));
	    if(array == NULL)
	    {
	        fprintf(stderr, "realloc error!\n");
	        return 1;
	    }
	    array[heapSize - 1] = tmp;
    }
    printf("The origen dataset:\n");
    for(i = 0; i < heapSize; i++)
    {
        printf("%d\t", array[i]);
    }
    printf("\n");


    /*构建小根堆并输出*/
    MinHeapCreat(array, heapSize);


    printf("Output the MinHeap:\n");
    for(i = 0; i < heapSize; i++)
    {
        printf("%d\t", array[i]);
    }
    printf("\n");


    /*构建大根堆并输出*/
    MaxHeapCreat(array, heapSize);
    printf("Output the MaxHeap:\n");
    for(i = 0; i < heapSize; i++)
    {
        printf("%d\t", array[i]);
    }
    /*堆排序*/
    HeapSort(array, heapSize);
    printf("Output the SortedHeap:\n");
    for(i = 0; i < heapSize; i++)
    {
        printf("%d\t", array[i]);
    }
    free(array);
	fclose(fp);


	return 0;
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值