`
flforever1213
  • 浏览: 123814 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

算法 之 堆 - 小结

阅读更多

之前我们讨论的堆,都把最大键值存储在根节点中,这种类型的堆可以看作是最大堆。

我们还可以创建另一种堆,把最键小值存储在根节点中,根节点以外的节点的键值,大于或等于存储在它父节点中的键值,这种类型的堆可以看作是最小堆。

具体是用最大堆还是最小堆,就根据我们自身的需要来选择了。

 

堆的算法到这里就讲完了,下面这段代码包括了之前讲过的堆的所有算法:

#include <stdio.h>
#include <stdlib.h>

void siftUp(int* heap, int index);
void siftDown(int* heap, int index);
void siftDown(int* heap, int siftDownTo, int index);
int* insertElement(int* heap, int element);
int* deleteElement(int* heap, int index);
int* makeHeap(int* array, int arrayLength);
void heapSort(int* heap);
void print(char* description, int* heap);

void siftUp(int* heap, int index)
{
	int heapLength = heap[0];

	if (index < 1 || index > heapLength)
		return;

	bool done = false;
	while(!done && index > 1)
	{
		if (heap[index] > heap[index / 2])
		{
			int temp = heap[index];
			heap[index] = heap[index / 2];
			heap[index / 2] = temp;
		}
		else
		{
			done = true;
		}

		index /= 2;
	}
}

void siftDown(int* heap, int index)
{
	int heapLength = heap[0];
	siftDown(heap, heapLength, index);
}

void siftDown(int* heap, int siftDownTo, int index)
{
	if (index < 1 || index * 2 > siftDownTo)
		return;

	bool done = false;
	while(!done && index * 2 <= siftDownTo)
	{
		index *= 2;

		if (index + 1 <= siftDownTo && heap[index + 1] > heap[index])
			index += 1;

		if (heap[index] > heap[index / 2])
		{
			int temp = heap[index];
			heap[index] = heap[index / 2];
			heap[index / 2] = temp;
		}
		else
		{
			done = true;
		}
	}
}

int* insertElement(int* heap, int element)
{
	int heapLength = heap[0];
	int resultHeapLength = heapLength + 1;

	// 创建一个长度为resultHeapLength+1的int数组
	int* resultHeap = (int*)malloc(sizeof(heap) * (resultHeapLength + 1));
	if (resultHeap == NULL)
		return NULL;

	resultHeap[0] = resultHeapLength;
	for (int i = 1; i <= heapLength; i++)
	{
		resultHeap[i] = heap[i];
	}

	resultHeap[resultHeapLength] = element;
	siftUp(resultHeap, resultHeapLength);

	return resultHeap;	
}

int* deleteElement(int* heap, int index)
{
	int heapLength = heap[0];
	if (index < 1 || index > heapLength)
		return heap;

	int x = heap[index];
	int y = heap[heapLength];

	int resultHeapLength = heapLength - 1;

	// 创建一个长度为resultHeapLength+1的int数组
	int* resultHeap = (int*)malloc(sizeof(heap) * (resultHeapLength + 1));
	if (resultHeap == NULL)
		return NULL;

	resultHeap[0] = resultHeapLength;
	for (int i = 1; i <= resultHeapLength; i++)
	{
		resultHeap[i] = heap[i];
	}

	if (index == resultHeapLength)
		return resultHeap;

	resultHeap[index] = y;
	if (y > x)
	{
		siftUp(resultHeap, index);
	}
	else
	{
		siftDown(resultHeap, index);
	}

	return resultHeap;
}

int* makeHeap(int* array, int arrayLength)
{
	if (array == NULL || arrayLength <= 0)
		return NULL;

	int heapLength = arrayLength;
	int* heap = (int*)malloc(sizeof(array) * (heapLength + 1));
	if (heap == NULL)
		return NULL;

	// heap[0]用来存储数组中堆数据的长度,堆数据heap[1]...heap[heapLength]  
	// 所以数组的实际长度是heapLength+1,我们只对从数组索引为1开始的heapLength个数据进行操作
	heap[0] = heapLength;
	for (int i = 0; i < arrayLength; i++)
	{
		heap[i + 1] = array[i];
	}

	for (int i = heapLength / 2; i >= 1; i--)
	{
		siftDown(heap, i);
	}

	return heap;
}

void heapSort(int* heap)
{
	if (heap == NULL)
		return;

	int heapLength = heap[0];
	int temp = 0;

	for (int i = heapLength; i >= 2; i--)
	{
		temp = heap[1];
		heap[1] = heap[i];
		heap[i] = temp;

		siftDown(heap, i - 1, 1);
	}
}

void print(char* description, int* heap)
{
	printf("%s:\t", description);

	int heapLength = heap[0];

	for(int i = 1; i <= heapLength; i++)
	{
		printf("%d ", heap[i]);
	}

	printf("\n");
}

void main()
{
	const int ARRAY_LENGTH = 10;
	int array[ARRAY_LENGTH] = { 4, 3, 8, 10, 11, 13, 7, 30, 17, 26 };

	int* heap = makeHeap(array, ARRAY_LENGTH);
	print("从数组初始化堆", heap);

	int* heapAfterInsert = insertElement(heap, 20);
	print("插入新数据20", heapAfterInsert);
	free(heap);

	int* heapAfterDelete = deleteElement(heapAfterInsert, 2);
	print("删除第2个数据", heapAfterDelete);
	free(heapAfterInsert);

	heapSort(heapAfterDelete);
	print("按非降序排序", heapAfterDelete);
	free(heapAfterDelete);

	getchar();
}

 

更多内容请参考:

算法 之 堆 - 简介

算法 之 堆 - Sift-up和Sift-down

算法 之 堆 - 插入和删除

算法 之 堆 - 创建堆

算法 之 堆 - 排序

2
6
分享到:
评论

相关推荐

    数据结构算法与应用-C++语言描述

    3.4.8 小结 96 3.5 间接寻址 99 3.5.1 基本概念 99 3.5.2 操作 100 3.6 模拟指针 102 3.6.1 SimSpace的操作 103 3.6.2 采用模拟指针的链表 106 3.7 描述方法的比较 110 3.8 应用 111 3.8.1 箱子排序 111 3.8.2 基数...

    查找算法和排序算法小结

    包括顺序查找、二分查找、选择排序、冒泡排序,二分排序,插入排序,希尔排序,堆排序,归并排序等

    数据结构、算法与应用--C++语言描述

    3.4.8 小结 96 3.5 间接寻址 99 3.5.1 基本概念 99 3.5.2 操作 100 3.6 模拟指针 102 3.6.1 SimSpace的操作 103 3.6.2 采用模拟指针的链表 106 3.7 描述方法的比较 110 3.8 应用 111 3.8.1 箱子排序 111 3.8.2 基数...

    数据结构算法与应用-C__语言描述

    3.4.8 小结 96 3.5 间接寻址 99 3.5.1 基本概念 99 3.5.2 操作 100 3.6 模拟指针 102 3.6.1 SimSpace的操作 103 3.6.2 采用模拟指针的链表 106 3.7 描述方法的比较 110 3.8 应用 111 3.8.1 箱子排序 111 3.8.2 基数...

    数据结构算法与应用-C C++语言描述

    3.4.8 小结 96 3.5 间接寻址 99 3.5.1 基本概念 99 3.5.2 操作 100 3.6 模拟指针 102 3.6.1 SimSpace的操作 103 3.6.2 采用模拟指针的链表 106 3.7 描述方法的比较 110 3.8 应用 111 3.8.1 箱子排序 111 3.8.2 基数...

    数据结构算法与应用-C++语言描述.rar

    3.4.8 小结 96 3.5 间接寻址 99 3.5.1 基本概念 99 3.5.2 操作 100 3.6 模拟指针 102 3.6.1 SimSpace的操作 103 3.6.2 采用模拟指针的链表 106 3.7 描述方法的比较 110 3.8 应用 111 3.8.1 箱子排序 111 ...

    数据结构与算法分析-Java语言描述(第2版)_2_2

    小结 练习 参考文献第6章 优先队列(堆) 6.1 模型 6.2 一些简单的实现 6.3 二叉堆 6.3.1 结构性质 6.3.2 堆序性质 6.3.3 基本的堆操作 6.3.4 其他的堆操作 6.4 优先队列的应用 6.4.1 选择问题...

    数据结构与算法分析-Java语言描述(第2版)_1_2

    小结 练习 参考文献第6章 优先队列(堆) 6.1 模型 6.2 一些简单的实现 6.3 二叉堆 6.3.1 结构性质 6.3.2 堆序性质 6.3.3 基本的堆操作 6.3.4 其他的堆操作 6.4 优先队列的应用 6.4.1 选择问题...

    Delphi算法与数据结构 源码(上)

    1.4小结 第2章数组 2.1数组 2.2Delphi中的数组类型 2.3TList类和指针数组 2.4磁盘数组 2.5小结 第3章链表、栈和队列 3.1单链表 3.2双向链表 3.3链表的优缺点 3.4栈 3.5队列 3.6小结 .第4章查找 4.1比较...

    Delphi算法与数据结构 源码(下)

    1.4小结 第2章数组 2.1数组 2.2Delphi中的数组类型 2.3TList类和指针数组 2.4磁盘数组 2.5小结 第3章链表、栈和队列 3.1单链表 3.2双向链表 3.3链表的优缺点 3.4栈 3.5队列 3.6小结 .第4章查找 4.1比较...

    数据结构与算法分析

     小结   练习   参考文献  第2章 算法分析   2.1 数学基础   2.2 模型   2.3 要分析的问题   2.4 运行时间计算   2.4.1 一个简单的例子   2.4.2 一般法则   2.4.3 最大子序列...

    六种排序算法小结PDF

    插入排序、选择排序、冒泡排序、归并排序、快速排序和堆排序。 有详细的思路及算法分析、伪代码、图解、示例代码等。 比较列表中的相邻元素,如果它们是逆序的话就交换它们的位置。重复多次后,最大的元素就“沉到”...

    C/C++常用算法手册.秦姣华(有详细书签).rar

    1.9 小结 14 第2章 数据结构 15 2.1 数据结构概述 15 2.1.1 什么是数据结构 15 2.1.2 数据结构中的基本概念 16 2.1.3 数据结构的内容 16 2.1.4 数据结构的分类 18 2.1.5 数据结构的几种存储方式 18 2.1.6 ...

    数据结构与算法分析_Java语言描述(第2版)

    小结 练习 参考文献 第2章 算法分析 2.1 数学基础 2.2 模型 2.3 要分析的问题 2.4 运行时间计算 2.4.1 一个简单的例子 2.4.2 一般法则 2.4.3 最大子序列和问题的求解 2.4.4 运行时间中的对数 2.4.5 检验你的分析 ...

    数据结构与算法

    本章小结 ……………………………………… 习题 …………………………………………… 第 章 表 ……………………………………… 表 ………………………………… 用数组实现表………………………… 用指针实现表……...

Global site tag (gtag.js) - Google Analytics