堆排序

#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);
//修改堆中某一元素的值为key
void 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;
}
//修改堆中某一元素的值为key
void 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);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值