堆排序

来源:互联网 发布:可视化数据调度平台 编辑:程序博客网 时间:2024/05/16 15:30
#include <stdio.h>#include <stdlib.h>#include <string.h>#define PARENT(x) ((x-1)>>1)#define LEFT(x) (((x)<<1)+1)#define RIGHT(x) (((x)<<1)+2)//#define LEFT(x) ((x)<<1)//#define RIGHT(x) (((x)<<1)+1)int count = 0;void max_heapfiy(int *arr, int len, int i);void build_max_heap(int *arr, int len);void heap_sort(int *arr, int len);//返回最大元素int heap_max(int *arr, int len);//返回最大元素,并删除它,之后保持堆的性质int extract_max(int *arr, int len);//向堆中插入一个值为key的元素,返回插入后的长度int insert_key(int *arr, int len, int key);//修改堆中某一元素的值为keyvoid modify_key(int *arr, int len, int key, int i);int main(){    printf("before build heap:\n");    int i = 0;    int num = 12;//00000;    int *arr = (int*)malloc(num * sizeof(int));// = {0};//3,9,6,7,2,5,8,1,10,4};    srand(time(NULL));    int t = num;    for(i = 0; i < num; i++)    {        arr[i] = rand()%num + 11;        printf("%d,", arr[i]);    }    printf("\n");    build_max_heap(arr, num);    printf("after build heap\n");    for(i = 0; i < num; i++)    {        printf("%d,", arr[i]);    }    printf("\n");    //insert_key(arr, num-1, arr[num-1]);    //heap_sort(arr, num);    int key = 13;    modify_key(arr, num, key, 4);    printf("after motify heap:\n");    for(i = 0; i < num; i++)    {        printf("%d,", arr[i]);    }    printf("\n");    printf("extract max queue:\n");    for(i = 0; i < num; i++)    {        printf("%d,", extract_max(arr, num - i));    }    printf("\n");        printf("efficient is %d\n", count);    return 0;}/* * 中心思想: 首先我们假设此过程之前以i节点为根的树已具有堆的性质 * 每次我们从 i 与他的两个孩子中找出最大的一个与根进行比较 * 如果恰好i是最大的,那么此过和结束,如果i不是最大的,便将i与最大的一个 * 孩子进行交换,使其成为根,然后再从该孩子入手,递归的执行此过程。 */void max_heapfiy(int *arr, int len, int i){    int l = LEFT(i);    int r = RIGHT(i);//    printf("i = %d, l = %d, r = %d\n", i, l, r);    int max = i;//假设当前元素为最大元素    //只变换下标,找出最大元素    if(l < len && arr[i] < arr[l])    {        max = l;    }    if(r < len && arr[max] < arr[r])    {        max = r;//max标注当前最大元素,但不一定是堆的根    }    //交换元素本身    //有个先决假想条件:除了本次max_heapfiy外,其他层的堆都假设是建好的。    //如果i不是当前最大的,则将i变为当前最大的,然后    if(max != i)    {        int tmp = arr[i];        arr[i] = arr[max];        arr[max] = tmp;//交换后max标注下一次建堆的选择元素        max_heapfiy(arr, len, max);    }    count++;    return ;}/*  * 中心思想,由于n元素的堆的叶子结点的下标为: n/2+1 到 n * 所以我们从最后一个非叶子结点 n/2 往上建堆即可(此处以下标为0进行说明) */void build_max_heap(int *arr, int len){    int i = len / 2;    for(; i >= 0; i--)    {       max_heapfiy(arr,len, i);    }    return ;}void heap_sort(int *arr, int len){    int size = len;    build_max_heap(arr, len);    while(--size >= 1)    {        int max = arr[0];        arr[0] = arr[size];        arr[size] = max;        max_heapfiy(arr, size, 0);    }}int heap_max(int *arr, int len){    if(len <= 0)    {        return 1<<32;    }    return arr[0];}int extract_max(int *arr, int len){    if(len <= 0)    {        printf("under overflow!\n");        exit(0);    }    int max = arr[0];    arr[0] = arr[len-1];    max_heapfiy(arr, len-1, 0);    return max;}int insert_key(int *arr, int len, int key){    if(len < 0)        return -1;    int i = len;    arr[i] = key;    while(i > 0 && arr[PARENT(i)] < arr[i])    {        int tmp = arr[PARENT(i)];        arr[PARENT(i)] = arr[i];        arr[i] = tmp;        i = PARENT(i);    }    return len+1;}//修改堆中某一元素的值为keyvoid modify_key(int *arr, int len, int key, int i){    if(len <= 0)        return;    //modify to key    //arr[i], key;    //rebuild the heap    if(arr[i] < key)    {        arr[i] = key;        while(i > 0 && arr[PARENT(i)] < arr[i])        {            int tmp = arr[PARENT(i)];            arr[PARENT(i)] = arr[i];            arr[i] = tmp;            i = PARENT(i);        }    }    else    {        arr[i] = key;        max_heapfiy(arr, len, i);    }}