最大最小堆

1 最大最小堆定义

堆的定义是:n个元素的序列{k1,k2,…,kn},当且仅当满足如下关系时被称为堆

    (1)Ki <= k2i 且 ki <= k2i+1

  或 (2) Ki >= k2i 且 ki >= k2i+1  (i = 1,2,…[n/2])

当满足(1)时,为最小堆,当满足(2)时,为最大堆。

若将序列对应成二叉树,便是一颗完全二叉树,2i和2i+1节点分别是节点i的左右子节点,下图所示便是一个最大堆例子:

最小堆例子:

2 建立最大最小堆

 最大最小堆的建立方式,较为常见的是,从最后一个元素开始,对堆中元素进行逐层下移。

最大堆建立:

/*
*@func: down shift element in heap
*@param heap: heap to shift
*@param index: the start location of element to shift
*@param len: number of elements already in heap
*/
void maxHeapDownShift(int heap[], int index, int len)
{
	if (heap == NULL || index <= 0 || len <= 0 || index > len)
		return;
	int large = 0;
	int left = index * 2;
	int right = index *2 + 1;

	if (left <= len && heap[left] > heap[index])
		large = left;
	else
		large = index;

	if (right <= len && heap[right] > heap[large])
		large = right;

	if (large != index)
	{
		int tmp = heap[index];
		heap[index] = heap[large];
		heap[large] = tmp;

		maxHeapDownShift(heap, large, len);
	}
}
/*
*@func: create max heap
*@param heap: the target heap
*@param len: number of elements in heap to be created
*/
void createMaxHeap(int heap[], int len)
{
	if (heap == NULL || len < 0)
		return;

	int index = len / 2;
	for (; index >= 1; -- index)
	{
		maxHeapDownShift(heap, index, len);
	}
}

最小堆建立:

void minHeapShift(int heap[], int index, int len)
{
	if (heap == NULL || index <=0 || len <=0 || index > len)
		return;

	int smallIndex = -1;
	int left = index * 2;
	int right = index * 2 + 1;

	if (left <= len && heap[left] < heap[index])
		smallIndex = left;
	else
		smallIndex = index;

	if (right <= len && heap[right] < heap[smallIndex])
		smallIndex = right;

	if (smallIndex != index)
	{
		int temp = heap[index];
		heap[index] = heap[smallIndex];
		heap[smallIndex] = temp;

		minHeapShift(heap, smallIndex, len);
	}
}
void createMinHeap(int heap[], int len)
{
	if (heap == NULL || len <= 0)
		return;

	int index = len / 2;
	for(; index >= 1; -- index)
	{
		minHeapShift(heap, index, len);
	}
}

3 向堆中插入一个元素

/*
*@func:insert new element into heap
*@param heap, the heap  we insert to
*@param value, the element to be inserted
*@param currentLen, number of elements already in the heap
*@param maxLen, max number of elements the heap can contain
*@return: -1 error in heap, -2 no more sapce in heap, 1 insert success
*/
int insertToHeap(int heap[], int value, int *currentLen, int maxLen)
{
	if (heap == NULL || maxLen <= 0 || currentLen == NULL)
		return -1;
	if (*currentLen >= maxLen)
		return -2;

	int index = *currentLen + 1;
	int root = index >> 1;
	for (; root >= 1 && value > heap[root];)
	{
		heap[index] = heap[root];
		index >>= 1;
		root = index >> 1;
	}

	heap[index] = value;
	++ (*currentLen);
	return 1;
}

4 删除堆顶元素

/*
*@func: remove root of heap
*@param heap: the heap remove from
*@param currentLen: number of elements already in the heap
*@return: -1 error in heap, 1 remove success
*/
int removeFromHeap(int heap[], int *currentLen)
{
	if (heap == NULL || currentLen == NULL || (*currentLen) <= 0)
		return -1;

	if (*currentLen == 1)
	{
		heap[1] = 0;
		-- (*currentLen);
		return 1;
	}
	int index = *currentLen;
	int last = heap[index --];
	int current = 1, child = 2;
	while (child <= index)
	{	
		if (child < index && heap[child] < heap[child + 1])
			++ child;

		if (last >= heap[child])
			break;

		heap[current] = heap[child];
		current = child;
		child *= 2;
	}

	heap[current] = last;
	-- (*currentLen);
	return 1;
}

5 删除堆中指定位置的元素

void maxHeapUpShift(int heap[], int index, int len)
{
	if (heap == NULL || index <= 0 || len <= 0 || index > len)
		return;
	int tmp = 0;
	int i = index;
	int root = i >> 1;
	for (; root >= 1 && heap[root] < heap[i];)
	{
		tmp = heap[i];
		heap[i] = heap[root];
		heap[root] = tmp;
		i >> 1;
		root = i >> 1;
	}
}
/*
*@func: remove element from given index
*@param heap: pointer to heap array
*@param index: given location contain the element to be removed
*@param currentSize: pointer to current size of heap
*@return: -1 error in heap, -2 error index,
*/
int removeFromIndex(int heap[], int index, int *currentSize)
{
	if (heap == NULL || index <= 0 || currentSize == NULL || *currentSize <= 0)
		return -1;
	if (index > *currentSize)
		return -2;

	int last = heap[*currentSize];
	if (last == heap[index])
	{
		heap[*currentSize] = 0;
		-- (*currentSize);
		return 1;
	}
	else if (last < heap[index])
	{
		heap[index] = last;
		heap[*currentSize] = 0;
		maxHeapDownShift(heap, index, *currentSize);
		-- (*currentSize);
		return 1;
	}
	else
	{
		heap[index] = last;
		heap[*currentSize] = 0;
		maxHeapUpShift(heap, index, *currentSize);
		-- (*currentSize);
		return 1;
	}
}

6 堆排序

void heapSort(int heap[], int len)
{
	if (heap == NULL || len <= 0)
		return;

	createMaxHeap(heap, len);
	int temp = heap[1];
	heap[1] = heap[len];
	heap[len] = temp;

	heapSort(heap, len - 1);
}

7 一个测试例子

找出n个数中最小的k个。

int main()
{
	int k = 10;
	int currentSize = k;
	int maxSize = k * 2;
	int *maxHeap = (int*)malloc(sizeof(int) * (maxSize+1));
	int *minHeap = (int*)malloc(sizeof(int) * (maxSize+1));
	FILE *fp = fopen("data.txt", "r");
	if (maxHeap == NULL || fp == NULL || minHeap == NULL)
		return 0;

	int i;
	for (i = 1; i <= k; ++ i)
	{
		fscanf(fp, "%d", &maxHeap[i]);
		minHeap[i] = maxHeap[i];
	}

	createMaxHeap(maxHeap, k);
	createMinHeap(minHeap, k);

	int newData;
	while (fscanf(fp, "%d", &newData) != EOF)
	{
		if (newData < maxHeap[1])
		{
			maxHeap[1] = newData;
			maxHeapShift(maxHeap, 1, k);
		}
		else if (newData > minHeap[1])
		{
			minHeap[1] = newData;
			minHeapShift(minHeap, 1, k);
		}
	}

	for (i = 1; i <= k; ++ i)
		printf("%d ", maxHeap[i]);
	printf("\n");

	for (i = 1; i <= k; ++ i)
		printf("%d ", minHeap[i]);
	printf("\n");

	heapSort(maxHeap, k);
	for (i = 1; i <= k; ++ i)
		printf("%d ", maxHeap[i]);
	printf("\n");

	heapSort(minHeap, k);
	for (i = 1; i <= k; ++ i)
		printf("%d ", minHeap[i]);
	printf("\n");

	createMaxHeap(maxHeap, k);
	printf("max heap\n");
	for (i = 1; i <= currentSize; ++ i)
		printf("%d ", maxHeap[i]);
	printf("\n");
	int res = insertToHeap(maxHeap, 2013, ¤tSize, maxSize);
	printf("insert %d\n", res);
	for (i = 1; i <= currentSize; ++ i)
		printf("%d ", maxHeap[i]);
	printf("\n");
	printf("delete root\n");
	removeFromHeap(maxHeap, ¤tSize);
	for (i = 1; i <= currentSize; ++ i)
		printf("%d ", maxHeap[i]);
	printf("\n");
	res = removeFromIndex(maxHeap,6, ¤tSize);
	printf("remove from index %d\n", res);
	for (i = 1; i <= currentSize; ++ i)
		printf("%d ", maxHeap[i]);
	printf("\n");

	fclose(fp);
	free(maxHeap);
	free(minHeap);
	return 0;
}










 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值