C++实现堆排序示例

目录
  • 堆的实现
    • Heap.h 堆的管理及接口
    • Heap.c 堆各个接口功能的实现
    • test.c测试

堆的实现

Heap.h 堆的管理及接口

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

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}Heap;

//堆的向下调整算法
void AdjustDown(HPDataType* a, int n, int root);
//堆的向上调整算法
void AdjustUp(HPDataType* a, int child);
//堆的初始化
void HeapInit(Heap* php, HPDataType* a,int n);
//堆的销毁
void HeapDestroy(Heap* php);
//堆的插入
void HeapPush(Heap* php, HPDataType x);
//堆的删除
void HeapPop(Heap* php);
//堆里的数据个数
int HeapSize(Heap* php);
//判断堆是否为空
int HeapEmpty(Heap* php);
//取堆顶数据
HPDataType HeapTop(Heap* php);

Heap.c 堆各个接口功能的实现

• 堆的插入:将x插入下标为size的位置,++size然后使用向上调整算法调整
• 堆的删除(删栈顶数据):将栈顶数据和下标为size-1位置的数据交换,然后–size,使用向下调整算法调整

#include "Heap.h"

//堆向下调整算法
//建小堆
void AdjustDown(HPDataType* a, int n, int root)
{
	int parent = root;
	int child = parent * 2 + 1;
	//孩子超过数组下标结束
	while (child < n)
	{
		//child始终左右孩子中小的那个
		if (a[child + 1] < a[child] && child + 1 <n)//防止没有右孩子
		{
			++child;
		}
		//小的往上浮,大的往下沉
		if (a[child] < a[parent])
		{
			int tem = a[parent];
			a[parent] = a[child];
			a[child] = tem;
			parent = child;
			child = parent * 2 + 1;
		}
		//中途child>parent则已满足小堆,直接break
		else
		{
			break;
		}
	}
}
//堆的向上调整算法
//建小堆
void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			int tem = a[parent];
			a[parent] = a[child];
			a[child] = tem;
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
//堆的初始化
void HeapInit(Heap* php, HPDataType* a, int n)
{
	assert(php);
	assert(a);
	php->a = (HPDataType*)malloc(n * sizeof(HPDataType));
	if (php->a == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	for (int i = 0; i < n; i++)
	{
		php->a[i] = a[i];
	}
	//建堆
	for (int i = (n - 2) / 2; i >= 0; --i)
	{
		AdjustDown(php->a, n, i);
	}
	php->capacity = n;
	php->size = n;
}
//堆的销毁
void HeapDestroy(Heap* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->capacity = 0;
	php->size = 0;
}
//堆的插入
void HeapPush(Heap* php, HPDataType x)
{
	assert(php);
	if (php->size == php->capacity)
	{
		HPDataType* tem = (HPDataType*)realloc(php->a,php->capacity * 2 * sizeof(HPDataType));
		if (tem == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		php->a = tem;
		php->capacity *= 2;
	}
	php->a[php->size] = x;
	++php->size;
	AdjustUp(php->a,php->size - 1);
}
//堆的删除
void HeapPop(Heap* php)
{
	assert(php);
	assert(php->size > 0);
	HPDataType tem = php->a[php->size - 1];
	php->a[php->size - 1] = php->a[0];
	php->a[0] = tem;
	--php->size;
	AdjustDown(php->a, php->size, 0);
}
//堆里的数据个数
int HeapSize(Heap* php)
{
	assert(php);
	return php->size;
}
//判断堆是否为空
//为空返回1,不为空返回0
int HeapEmpty(Heap* php)
{
	assert(php);
	return php->size == 0 ? 1 : 0;
}
//取堆顶数据
HPDataType HeapTop(Heap* php)
{
	assert(php);
	assert(php->size > 0);
	return php->a[0];
}

test.c测试

#include "Heap.h"

void TestHeap()
{
	int arr[] = { 27, 28, 65, 25, 15, 34, 19, 49, 18, 37 };
	Heap hp;
	HeapInit(&hp, arr, sizeof(arr)/sizeof(int));
	while (!HeapEmpty(&hp))
	{
		printf("%d ", HeapTop(&hp));
		HeapPop(&hp);

	}
	printf("\n");
	HeapDestroy(&hp);
}
int main()
{
	TestHeap();
	return 0;
}

以上就是C++实现堆排序示例的详细内容,更多关于C++实现堆排序的资料请关注我们其它相关文章!

(0)

相关推荐

  • C++ 自由存储区是否等价于堆你知道吗

    目录 free store" VS "heap" 问题的来源 结论 free store" VS "heap" 当我问你C++的内存布局时,你大概会回答: "在C++中,内存区分为5个区,分别是堆.栈.自由存储区.全局/静态存储区.常量存储区". 如果我接着问你自由存储区与堆有什么区别,你或许这样回答: "malloc在堆上分配的内存块,使用free释放内存,而new所申请的内存则是在自由存储区上,使用delete来

  • C++实现数据文件存储与加载

    本文实例为大家分享了C++实现数据文件存储与加载的具体代码,供大家参考,具体内容如下 首先请先确认已经安装好了opencv3及以上版本. #include <opencv2/opencv.hpp> #include <iostream> #include <string> using namespace cv; using namespace std; 存储 then int main() { //创造一些要存的数据先 string words = "hell

  • C++静态变量,常量的存储位置你真的了解吗

    目录 引言 C++对内存的划分如何落实在Linux上 自由存储区和堆之间的问题 栈 常量区 静态存储区 静态局部变量 静态局部变量.静态全局变量.全局变量的异同 总结 引言 在动态内存的博客中,我提到: 在Linux 内存管理的博客中,我提到: 尽管都有尽可能完全的描述,并且两者大致意思没有冲突.而之所以令我一直感到略有不同,越看越迷糊的原因是:第一张图讲的其实是C++在概念上对内存的划分,第二张图讲的是Linux对虚拟内存进行的划分. 前者是概念上的,也是C++程序在运行时会切实执行的,而后者

  • 详解C++中的自动存储

    C++有3种管理数据内存的方式即自动存储(栈存储).静态存储和动态存储(堆存储).在不同的方式下,内存的分配形式和存在时间的长短都不同. 下面对自动存储进行说明. 自动存储(栈存储) 对于函数的形参.内部声明的变量及结构变量等,编译器将在函数执行时为形参自动分配存储空间,在执行到变量和结构变量等的声明语句时为其自动分配存储空间,因此称其为自动变量(Automatic Variable),有的教科书也称其为局部变量,在函数执行完毕返回时,这些变量将被撤销,对应的内存空间将被释放. 事实上,自动变量

  • C++ 数据结构 堆排序的实现

    堆排序(heapsort)是一种比较快速的排序方式,它的时间复杂度为O(nlgn),并且堆排序具有空间原址性,任何时候只需要有限的空间来存储临时数据.我将用c++实现一个堆来简单分析一下. 堆排序的基本思想为: 1.升序排列,保持大堆:降序排列,保持小堆: 2.建立堆之后,将堆顶数据与堆中最后一个数据交换,堆大小减一,然后向下调整:直到堆中只剩下一个有效值: 下面我将简单分析一下: 第一步建立堆: 1.我用vector顺序表表示数组: 2.用仿函数实现大小堆随时切换,实现代码复用: 3.实现向下

  • C++实现堆排序示例

    目录 堆的实现 Heap.h 堆的管理及接口 Heap.c 堆各个接口功能的实现 test.c测试 堆的实现 Heap.h 堆的管理及接口 #include<stdio.h> #include<stdlib.h> #include<assert.h> typedef int HPDataType; typedef struct Heap { HPDataType* a; int size; int capacity; }Heap; //堆的向下调整算法 void Adj

  • Go 数据结构之堆排序示例详解

    目录 堆排序 堆排序过程 动画显示 开始堆排序 代码实现 总结 堆排序 堆排序是一种树形选择排序算法. 简单选择排序算法每次选择一个关键字最小的记录需要 O(n) 的时间,而堆排序选择一个关键字最小的记录需要 O(nlogn)的时间. 堆可以看作一棵完全二叉树的顺序存储结构. 在这棵完全二叉树中,如果每个节点的值都大于等于左边孩子的值,称为大根堆(最大堆.又叫大顶堆).如果每个节点的值都小于等于左边孩子的值,称为小根堆(最小堆,小顶堆). 可以,用数学符号表示如下: 堆排序过程 构建初始堆 在输

  • 解读堆排序算法及用C++实现基于最大堆的堆排序示例

    1.堆排序定义 n个关键字序列Kl,K2,-,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质): (1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤   ) 若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字. [例]关键字序列(10,15,56,25,30,70)和(70,56,30,25,15,10)分别满足堆性质(1

  • Java算法之堆排序代码示例

    堆是一种特殊的完全二叉树,其特点是所有父节点都比子节点要小,或者所有父节点都比字节点要大.前一种称为最小堆,后一种称为最大堆. 比如下面这两个: 那么这个特性有什么作用?既然题目是堆排序,那么肯定能用来排序.想要用堆排序首先要创建一个堆,如果对4 3 6 2 7 1 5这七个数字做从小到大排序,需要用这七个数创建一个最大堆,来看代码: public class HeapSort { private int[] numbers; private int length; public HeapSor

  • Swift实现堆排序算法的代码示例

    算法思想 堆排序利用了最大堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单. 1.用最大堆排序的基本思想 (1)先将初始文件R[1..n]建成一个最大堆,此堆为初始的无序区 (2)再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key (3)由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-

  • python下实现二叉堆以及堆排序的示例

    堆是一种特殊的树形结构, 堆中的数据存储满足一定的堆序.堆排序是一种选择排序, 其算法复杂度, 时间复杂度相对于其他的排序算法都有很大的优势. 堆分为大头堆和小头堆, 正如其名, 大头堆的第一个元素是最大的, 每个有子结点的父结点, 其数据值都比其子结点的值要大.小头堆则相反. 我大概讲解下建一个树形堆的算法过程: 找到N/2 位置的数组数据, 从这个位置开始, 找到该节点的左子结点的索引, 先比较这个结点的下的子结点, 找到最大的那个, 将最大的子结点的索引赋值给左子结点, 然后将最大的子结点

  • Python实现的堆排序算法示例

    本文实例讲述了Python实现的堆排序算法.分享给大家供大家参考,具体如下: 堆排序的思想: 堆是一种数据结构,可以将堆看作一棵完全二叉树,这棵二叉树满足,任何一个非叶节点的值都不大于(或不小于)其左右孩子节点的值. 将一个无序序列调整为一个堆,就可以找出这个序列的最大值(或最小值),然后将找出的这个值交换到序列的最后一个,这样有序序列就元素就增加一个,无序序列元素就减少一个,对新的无序序列重复这样的操作,就实现了排序. 堆排序的执行过程: 1.从无序序列所确定的完全二叉树的第一个非叶子节点开始

  • C语言植物大战数据结构堆排序图文示例

    目录 TOP.堆排序前言 一.向下调整堆排序 1.向下调整建堆 建堆的技巧 建堆思路代码 2.向下调整排序 调整思路 排序整体代码 3.时间复杂度(难点) 向下建堆O(N) 向下调整(N*LogN) 二.向上调整堆排序 1.向上调整建堆 2.建堆代码 “大弦嘈嘈如急雨,小弦切切如私语”“嘈嘈切切错杂弹,大珠小珠落玉盘” TOP.堆排序前言 什么是堆排序?假如给你下面的代码让你完善堆排序,你会怎么写?你会怎么排? void HeapSort(int* a, int n) { } int main(

  • 理解二叉堆数据结构及Swift的堆排序算法实现示例

    二叉堆的性质 1.二叉堆是一颗完全二叉树,最后一层的叶子从左到右排列,其它的每一层都是满的 2.最小堆父结点小于等于其每一个子结点的键值,最大堆则相反 3.每个结点的左子树或者右子树都是一个二叉堆 下面是一个最小堆: 堆的存储 通常堆是通过一维数组来实现的.在起始数组为 0 的情形中: 1.父节点i的左子节点在位置 (2*i+1); 2.父节点i的右子节点在位置 (2*i+2); 3.子节点i的父节点在位置 floor((i-1)/2); 维持堆的性质 我们以最大堆来介绍(后续会分别给出最大堆和

  • C语言实现基于最大堆和最小堆的堆排序算法示例

    堆定义 堆实际上是一棵完全二叉树,其任何一非叶节点满足性质: Key[i]<=key[2i+1]&&Key[i]<=key[2i+2](小顶堆)或者:Key[i]>=Key[2i+1]&&key>=key[2i+2](大顶堆) 即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字. 堆排序的思想 利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单. 最大堆:所有节点的子节点比其

随机推荐