#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);
}
}
堆排序
最新推荐文章于 2024-11-16 13:27:03 发布