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

来源:互联网 发布:淘宝提醒发货不见了 编辑:程序博客网 时间:2024/06/05 12:03

大根堆小根堆的实现:以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;elselargest = 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;elseminimum = 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;elselargest = 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;elseminimum = 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;}




0 0