题目:
题解:
typedef struct Heap
{
int* array; //存放堆的数组
int capacity;//数组的容量
int len; //已存数组的大小
}Heap;
/*大小根堆切换开关*/
int HeapLen(Heap* hp); //heap获取当前的堆大小
void HeapSwap(int* pLeft, int* pRight); //heap交换父子结点的数值
bool HeapEmpty(Heap* hp); //heap判空
bool HeapFull(Heap* hp); //heap判满
int HeapGetTop(Heap* hp); //heap获取堆顶
void HeapInsert(Heap* hp, int dat,bool isMax); //heap向堆的尾部插入1个元素
void HeapDelete(Heap* hp,bool isMax); //heap删除堆顶
void HeapAdjustDown(Heap* hp, int parent,bool isMax); //heap向下调整
void HeapAdjustUp(Heap* hp, int child,bool isMax); //heap向上调整
Heap* CreateHeap(int size); //heap创建
void heapFree(Heap* hp); //heap释放空间
int HeapLen(Heap* hp)
{
return hp->len;
}
bool HeapEmpty(Heap* hp) //判空
{
if (HeapLen(hp) == 1)
{
return true;
}
return false;
}
bool HeapFull(Heap* hp) //判满
{
if (hp->capacity == hp->len)
{
return true;
}
return false;
}
void HeapSwap(int* pLeft, int* pRight)//交换数值
{
//交换堆中的父子结点
int temp;
temp = *pLeft;
*pLeft = *pRight;
*pRight = temp;
}
int HeapGetTop(Heap* hp)
{
return hp->array[1];
}
Heap* CreateHeap(int size)
{
Heap* heap = (Heap*)malloc(sizeof(Heap));
int heapLen = size + 1;//长度比size的长度大1才行
//给堆申请空间,初始化
heap->array = (int*)malloc(sizeof(int) * heapLen);
heap->capacity = heapLen; //容量
heap->len = 1; //当前大小
return heap;
}
void HeapAdjustDown(Heap* hp, int parent ,bool isMax)//向下调整
{
//标记左右孩子中最小孩子
int child = 2 * parent; //左孩子为2*parent 右孩子为 2*parent +1
int len = hp->len;
while (child < len)
{
if(isMax)
{
//大根堆 选最大的
//有右子树时 ,找左右孩子中最大的孩子
if ((child + 1 < len) && hp->array[child] < hp->array[child + 1])
child = child + 1;
//最大孩子大于双亲时 ,孩子与双亲数值交换,否则说明已经调好,不用继续
if (hp->array[child] > hp->array[parent])
{
HeapSwap(&hp->array[child], &hp->array[parent]);
parent = child;
child = parent << 1;
}
else
return;
}
else
{
//小根堆 选最小的
//有右子树时 ,找左右孩子中最小的孩子
if ((child + 1 < len) && hp->array[child] > hp->array[child + 1])
child = child + 1;
//最小孩子小于双亲时 ,孩子与双亲数值交换,否则说明已经调好,不用继续
if (hp->array[child] < hp->array[parent])
{
HeapSwap(&hp->array[child], &hp->array[parent]);
parent = child;
child = parent << 1;
}
else
return;
}
}
}
void HeapAdjustUp(Heap* hp, int child,bool isMax)//向上调整
{
//得到父母结点的位置
int parent = child / 2;
while (child > 1)
{
if(isMax)
{
//大根堆选择大的
//循环迭代从child当前位置一直迭代到0位置即对顶
if (hp->array[child] > hp->array[parent])
{
HeapSwap(&hp->array[child], &hp->array[parent]);
child = parent;
parent = child/2;
}
else
return;
}
else
{
//小根堆选择小的
//循环迭代从child当前位置一直迭代到0位置即对顶
if (hp->array[child] < hp->array[parent])
{
HeapSwap(&hp->array[child], &hp->array[parent]);
child = parent;
parent = child/2;
}
else
return;
}
}
}
void HeapDelete(Heap* hp,bool isMax)//删除堆顶
{
if (HeapEmpty(hp))
return;
//用最后一个元素覆盖堆顶,相当于删除堆顶
hp->array[1] = hp->array[hp->len - 1];
hp->len--;//删除最后一个元素 heap长度变短
HeapAdjustDown(hp, 1,isMax);//对第一个元素进行调整
}
void HeapInsert(Heap* hp, int dat,bool isMax)
{
if (HeapFull(hp))
{
//扩容
hp->capacity <<= 1;
hp->array = (int *) realloc(hp->array, hp->capacity * sizeof(int));
}
int child = 0;
int parent = 0;
//插入到最后一个元素的下一个位置
hp->array[hp->len++] = dat;
//调整刚插入元素,
//因为插入的是堆的尾部,需要堆向上调整
HeapAdjustUp(hp, hp->len - 1,isMax);
}
void heapFree(Heap* hp)
{
free(hp->array);
free(hp);
}
typedef struct
{
//左边是 最大堆 右边是小根堆
//0 1 3 5 7 9
Heap* maxLHeap;
Heap* minRHeap;
} MedianFinder;
MedianFinder* medianFinderCreate()
{
MedianFinder* newMedian = (MedianFinder* )malloc(sizeof(MedianFinder));
newMedian->maxLHeap = CreateHeap(128);
newMedian->minRHeap = CreateHeap(128);
return newMedian;
}
void medianFinderAddNum(MedianFinder* obj, int num)
{
//检查
int leftHeapLen = obj->maxLHeap->len;
int rightHeapLen = obj->minRHeap->len;
if (leftHeapLen <= rightHeapLen)
{
//插入左边的最小堆
//检查当前值 是否大于 右边的最小堆的堆顶值
if (!HeapEmpty(obj->minRHeap))
{
if (num > obj->minRHeap->array[1])
{
//保存当前右边最小堆堆顶值 需要准备移动到 左边 最大堆中
int moveValue = obj->minRHeap->array[1];
//将当前值放到 右边的最小堆 的堆顶
obj->minRHeap->array[1] = num;
HeapAdjustDown(obj->minRHeap, 1, false);
//插入到左边最大堆中
HeapInsert(obj->maxLHeap, moveValue, true);
//直接结束了
return;
}
}
//这里检查 num是小于右边的 最小堆 的堆顶值的
HeapInsert(obj->maxLHeap, num, true);
}
else
{
//插入右边的最大堆
//检查当前值 是否小于 左边的最大堆的堆顶值
if (!HeapEmpty(obj->maxLHeap))
{
if (num < obj->maxLHeap->array[1])
{
//保存当前左边最大堆堆顶值 需要准备移动到 右边 最小堆中
int moveValue = obj->maxLHeap->array[1];
//将当前值放到 左边的最da堆 的堆顶
obj->maxLHeap->array[1] = num;
HeapAdjustDown(obj->maxLHeap, 1, true);
//插入到右边最小堆中
HeapInsert(obj->minRHeap, moveValue, false);
//直接结束了
return;
}
}
//这里检查 num是大于左边的 最大堆 的堆顶值的
HeapInsert(obj->minRHeap, num, false);
}
}
double medianFinderFindMedian(MedianFinder* obj)
{
if (obj->maxLHeap->len == obj->minRHeap->len)
{
return (double)(obj->minRHeap->array[1] + obj->maxLHeap->array[1]) / 2;
}
return (double)obj->maxLHeap->array[1];
}
void medianFinderFree(MedianFinder* obj)
{
heapFree(obj->maxLHeap);
heapFree(obj->minRHeap);
free(obj);
}
/**
* Your MedianFinder struct will be instantiated and called as such:
* MedianFinder* obj = medianFinderCreate();
* medianFinderAddNum(obj, num);
* double param_2 = medianFinderFindMedian(obj);
* medianFinderFree(obj);
*/