数据结构-堆 C与C++的实现
堆,是一种完全二叉树。而且在这颗树中,父节点必然大于(对于小顶堆为小于)子节点。
关于树的概念不了解可以看这里:http://www.cnblogs.com/HongYi-Liang/p/7231440.html
由于堆是一种完全二叉树,很适合保存为数组的形式。如下图示意的堆,红色数字为数组索引,黑色数字为数组的值,那么这个堆保存为数组的形式:heap={9,8,5,6,7,1,4,0,3,2};
值得注意的是,在堆中,若设父亲的索引为i,左儿子的索引刚好等于2i,而右儿子的索引等于2i+1。这个公式会大量地出现在下边的程序中。
关键概念:
大顶堆:树根元素为最大值往叶子递减,(父节点总是大于子节点)
小顶堆:树根元素为最小值往叶子递增,(父节点总是小于子节点)
下为一个大顶堆的示意图,父节点总是大于子节点
在下面的程序中,C将以大顶堆的形式编写,C++以小顶堆的形式编写。
C语言
程序源码:
本例子为大顶堆,包含4个文件(如下图)
MaxHeap.c
#include "MaxHeap.h" bool MaxHeapConstructByBuffer(MaxHeap *heap,MAXHEAP_ELEM buff[],int length);
bool MaxHeapDesturct(MaxHeap *heap);
bool MaxHeap_getSize(MaxHeap *heap);
bool MaxHeap_isFull(MaxHeap *heap);
bool MaxHeap_isEmpty(MaxHeap *heap);
void MaxHeap_swap(MAXHEAP_ELEM *a,MAXHEAP_ELEM *b);
void MaxHeap_floating(MaxHeap *heap,int index);
void MaxHeap_sink(MaxHeap *heap, int index);
bool MaxHeap_push(MaxHeap *heap,MAXHEAP_ELEM data);
bool MaxHeap_push(MaxHeap *heap,MAXHEAP_ELEM data);
bool MaxHeap_pop(MaxHeap *heap,int index);
void MaxHeap_printfAll(MaxHeap *heap); bool MaxHeapConstructByBuffer(MaxHeap *heap,MAXHEAP_ELEM buff[],int length)
{
int i;
if(NULL != heap->iDatas)
{
return false;
}
heap->iHeapCapacity=length;
heap->iHeapSize=;
heap->iDatas = (MAXHEAP_ELEM*)malloc(sizeof(MAXHEAP_ELEM)*length);
for(i=;i<length;i++)
{
MaxHeap_push(heap,buff[i]);
}
return true;
} bool MaxHeapDesturct(MaxHeap *heap)
{
if(NULL == heap->iDatas)
{
return false;
}
free(heap->iDatas);
return true;
} bool MaxHeap_getSize(MaxHeap *heap)
{
return heap->iHeapSize;
} bool MaxHeap_isFull(MaxHeap *heap)
{
if(heap->iHeapCapacity == heap->iHeapSize)
{
return true;
}
return false;
} bool MaxHeap_isEmpty(MaxHeap *heap)
{
if( == heap->iHeapSize)
{
return true;
}
return false;
} void MaxHeap_swap(MAXHEAP_ELEM *a,MAXHEAP_ELEM *b)
{
MAXHEAP_ELEM temp;
temp=*a;
*a=*b;
*b=temp;
} void MaxHeap_floating(MaxHeap *heap,int index)
{
int i;
for(i=index;i>;i=(int)(i*0.5))
{
if(heap->iDatas[i-] > heap->iDatas[(int)(i*0.5-)] )
{
MaxHeap_swap(&heap->iDatas[i-],&heap->iDatas[(int)(i*0.5-)]);
}
else
{
break;
}
}
} void MaxHeap_sink(MaxHeap *heap, int index)
{
int i=index; while(i*<=heap->iHeapSize)
{
if(heap->iDatas[i-] < heap->iDatas[i*-])//it compare to left child
{
MaxHeap_swap(&heap->iDatas[i-],&heap->iDatas[i*-]);
if(i*+<=heap->iHeapSize && heap->iDatas[i-] < heap->iDatas[i*])//it compare to right child
{
MaxHeap_swap(&heap->iDatas[i-],&heap->iDatas[i*]);
}
/*index*/
i=i*;
}
else if(i*+<=heap->iHeapSize && heap->iDatas[i-] < heap->iDatas[i*])//it compare to right child
{
MaxHeap_swap(&heap->iDatas[i-],&heap->iDatas[i*]);
i=i*+;
}
else
{
break;
}
}
} bool MaxHeap_push(MaxHeap *heap,MAXHEAP_ELEM data)
{
if( MaxHeap_isFull(heap))
return false;
heap->iDatas[heap->iHeapSize]=data;
heap->iHeapSize++;
MaxHeap_floating(heap,heap->iHeapSize); return true;
} bool MaxHeap_pop(MaxHeap *heap,int index)
{
if(MaxHeap_isEmpty(heap))
return false;
heap->iDatas[index]=heap->iDatas[heap->iHeapSize-];
heap->iHeapSize--;
MaxHeap_sink(heap,index+); return true;
} void MaxHeap_printfAll(MaxHeap *heap)
{
int i;
printf("heap:");
for( i=;i<heap->iHeapSize;i++)
{
printf("%d ",heap->iDatas[i]);
}
printf("\r\n");
}
MaxHeap.h
#ifndef __MAXHEAP_H
#define __MAXHEAP_H #include <stdlib.h>
#include <stdio.h>
#include "Mystdbool.h" typedef int MAXHEAP_ELEM;
typedef struct
{
int iHeapCapacity;
int iHeapSize;
MAXHEAP_ELEM *iDatas;
}MaxHeap; bool MaxHeapConstructByBuffer(MaxHeap *heap,MAXHEAP_ELEM buff[],int length);
bool MaxHeapDesturct(MaxHeap *heap);
bool MaxHeap_getSize(MaxHeap *heap);
bool MaxHeap_isFull(MaxHeap *heap);
bool MaxHeap_isEmpty(MaxHeap *heap);
void MaxHeap_swap(MAXHEAP_ELEM *a,MAXHEAP_ELEM *b);
void MaxHeap_floating(MaxHeap *heap,int index);
void MaxHeap_sink(MaxHeap *heap, int index);
bool MaxHeap_push(MaxHeap *heap,MAXHEAP_ELEM data);
bool MaxHeap_push(MaxHeap *heap,MAXHEAP_ELEM data);
bool MaxHeap_pop(MaxHeap *heap,int index);
void MaxHeap_printfAll(MaxHeap *heap); #endif
Mystdbool.h(仅用于声明布尔类)
#ifndef _MYSTDBOOL_H
#define _MYSTDBOOL_H typedef enum Bool
{
false=,
true,
}bool; #endif
main.c
#include "MaxHeap.h" int main()
{
/*int buffer[10]={9,8,7,6,5,4,3,2,1,0};*/
int buffer[]={,,,,,,,,,};
MaxHeap heap={};
MaxHeapConstructByBuffer(&heap,buffer,);
MaxHeap_printfAll(&heap);
MaxHeap_pop(&heap,);
MaxHeap_printfAll(&heap);
MaxHeap_pop(&heap,);
MaxHeap_printfAll(&heap);
system("pause");
return ;
}
运行结果:
源码详解:
上浮:floating(int index)
- 将堆第index个元素与它的父亲比较,若小于它的父亲,则与它父亲交换数值。
- 上述过程如果发生,则把它继续上浮。
void MaxHeap_floating(MaxHeap *heap,int index)
{
int i;
for(i=index;i>;i=(int)(i*0.5))
{
if(heap->iDatas[i-] > heap->iDatas[(int)(i*0.5-)] )
{
MaxHeap_swap(&heap->iDatas[i-],&heap->iDatas[(int)(i*0.5-)]);
}
else
{
break;
}
}
}
添加元素:push(T data)
- 把元素添加到堆的最后。
- 并使用上浮方法把堆的最后一个元素上浮。
bool MaxHeap_push(MaxHeap *heap,MAXHEAP_ELEM data)
{
if( MaxHeap_isFull(heap))
return false;
heap->iDatas[heap->iHeapSize]=data;
heap->iHeapSize++;
MaxHeap_floating(heap,heap->iHeapSize); return true;
}
构建堆:MaxHeapConstructByBuffer()
- 用malloc为数据申请空间。
- 一个一个地将buff中的数据push()到堆中。
bool MaxHeapConstructByBuffer(MaxHeap *heap,MAXHEAP_ELEM buff[],int length)
{
int i;
if(NULL != heap->iDatas)
{
return false;
}
heap->iHeapCapacity=length;
heap->iHeapSize=0;
heap->iDatas = (MAXHEAP_ELEM*)malloc(sizeof(MAXHEAP_ELEM)*length);
for(i=0;i<length;i++)
{
MaxHeap_push(heap,buff[i]);
}
return true;
}
下沉:
- 从根开始,用父节点与左子节点比较。若父节点大于左子,则交换它们的值
- 用父节点与右子节点比较。若父节点大于右子,则交换它们的值。
- 若上述情况发生了,则继续下沉,直到无法下沉为止。
void MaxHeap_sink(MaxHeap *heap, int index)
{
int i=index; while(i*<=heap->iHeapSize)
{
if(heap->iDatas[i-] < heap->iDatas[i*-])//it compare to left child
{
MaxHeap_swap(&heap->iDatas[i-],&heap->iDatas[i*-]);
if(i*+<=heap->iHeapSize && heap->iDatas[i-] < heap->iDatas[i*])//it compare to right child
{
MaxHeap_swap(&heap->iDatas[i-],&heap->iDatas[i*]);
}
/*index*/
i=i*;
}
else if(i*+<=heap->iHeapSize && heap->iDatas[i-] < heap->iDatas[i*])//it compare to right child
{
MaxHeap_swap(&heap->iDatas[i-],&heap->iDatas[i*]);
i=i*+;
}
else
{
break;
}
}
}
删除元素:pop(int index)
- 把堆的第index个元素删除,并把堆的最后一个元素放到index处。
- 把堆的第index个元素下沉
bool MaxHeap_pop(MaxHeap *heap,int index)
{
if(MaxHeap_isEmpty(heap))
return false;
heap->iDatas[index]=heap->iDatas[heap->iHeapSize-];
heap->iHeapSize--;
MaxHeap_sink(heap,index+); return true;
}
C++
程序源码:
本例子为小顶堆,包含2个文件(如下图)
MyMinHeap.h:
此文件中为小顶堆的类模板。
#ifndef __MYMINHEAP_H
#define __MYMINHEAP_H
#include <iostream>
#include <vector> using namespace std; template <typename T>
class MyMinHeap
{
public:
MyMinHeap(T buff[],int length);
MyMinHeap(int capacity);
virtual ~MyMinHeap();
int getSize();
bool isFull();
bool isEmpty();
void swap(vector<T> &vec,int i,int j);
void floating(int index);
void sink(int index);
bool push(T data);
bool pop(int index);
//transval
void printfAll();
private:
int m_iHeapCapacity;
int m_iHeapSize;
vector<T> m_vecData;
}; template <typename T>
MyMinHeap<T>::MyMinHeap(T buff[],int length)
{
m_iHeapCapacity=length;
m_iHeapSize=;
m_vecData.resize(length);
for(int i=;i<length;i++)
{
push(buff[i]);
}
} template <typename T>
MyMinHeap<T>:: MyMinHeap(int capacity)
{
m_iHeapCapacity=capacity;
m_iHeapSize=;
m_vecData.resize(capacity);
} template <typename T>
MyMinHeap<T>::~MyMinHeap()
{ } template <typename T>
int MyMinHeap<T>::getSize()
{
return m_iHeapSize;
} template <typename T>
bool MyMinHeap<T>::isFull()
{
if(m_iHeapSize>=m_iHeapCapacity)
{
return true;
}
return false;
}
template <typename T>
bool MyMinHeap<T>::isEmpty()
{
if(m_iHeapSize==)
return true;
return false;
} template <typename T>
void MyMinHeap<T>::swap(vector<T> &vec,int i,int j)
{
T temp = vec[i];
vec[i]=vec[j];
vec[j]=temp;
} template <typename T>
void MyMinHeap<T>::floating(int index)
{
T temp;
for(int i=index;i>;i*=0.5)
{
if(m_vecData[i-]<m_vecData[i*0.5-] )
{
swap(m_vecData,i-,i*0.5-);
}
else
{
break;
}
}
} template <typename T>
void MyMinHeap<T>::sink(int index)
{
int i=index; while(i*<=m_iHeapSize)
{
if(m_vecData[i-]>m_vecData[i*-])//it compare to left child
{
swap(m_vecData,i-,i*-);
if(i*+<=m_iHeapSize && m_vecData[i-]>m_vecData[i*])//it compare to right child
{
swap(m_vecData,i-,i*);
}
/*index*/
i=i*;
}
else if(i*+<=m_iHeapSize && m_vecData[i-]>m_vecData[i*])//it compare to right child
{
swap(m_vecData,i-,i*);
i=i*+;
}
else
{
break;
}
}
} template <typename T>
bool MyMinHeap<T>::push(T data)
{
if(isFull())
return false;
m_vecData[m_iHeapSize]=data;
m_iHeapSize++;
floating(m_iHeapSize); return true;
} template <typename T>
bool MyMinHeap<T>::pop(int index)
{
if(isEmpty())
return false;
m_vecData[index]=m_vecData[m_iHeapSize-];
m_iHeapSize--;
sink(index+); return true;
} template <typename T>
void MyMinHeap<T>::printfAll()
{
cout<<"heap:";
for(int i=;i<m_iHeapSize;i++)
{
cout<<m_vecData[i]<<" ";
}
cout<<endl<<endl;
} #endif
main.h:
主程序用于测试运行。
#include <iostream>
#include "MyMinHeap.h"
using namespace std; int main()
{
int buffer[]={,,,,,,,,,};
MyMinHeap<int> heap(buffer,);
heap.printfAll();
heap.pop();
heap.printfAll();
heap.push();
heap.printfAll();
system("pause");
return ;
}
运行结果:
源码详解:
上浮:floating(int index)
- 将堆第index个元素与它的父亲比较,若小于它的父亲,则与它父亲交换数值。
- 上述过程如果发生,则把它继续上浮。
template <typename T>
void MyMinHeap<T>::floating(int index)
{
T temp;
for(int i=index;i>;i*=0.5)
{
if(m_vecData[i-]<m_vecData[i*0.5-] )
{
swap(m_vecData,i-,i*0.5-);
}
else
{
break;
}
}
}
添加元素:push(T data)
- 把元素添加到堆的最后。
- 并使用上浮方法把堆的最后一个元素上浮。
template <typename T>
bool MyMinHeap<T>::push(T data)
{
if(isFull())
return false;
m_vecData[m_iHeapSize]=data;
m_iHeapSize++;
floating(m_iHeapSize); return true;
}
构造函数:使用数组构建堆:
连续使用push()把buff中所有元素一个一个地加入堆中。
template <typename T>
MyMinHeap<T>::MyMinHeap(T buff[],int length)
{
m_iHeapCapacity=length;
m_iHeapSize=;
m_vecData.resize(length);
for(int i=;i<length;i++)
{
push(buff[i]);
}
}
下沉:
- 从根开始,用父节点与左子节点比较。若父节点大于左子,则交换它们的值
- 用父节点与右子节点比较。若父节点大于右子,则交换它们的值。
- 若上述情况发生了,则继续下沉,直到无法下沉为止。
template <typename T>
void MyMinHeap<T>::sink(int index)
{
int i=index; while(i*<=m_iHeapSize)
{
if(m_vecData[i-]>m_vecData[i*-])//it compare to left child
{
swap(m_vecData,i-,i*-);
if(i*+<=m_iHeapSize && m_vecData[i-]>m_vecData[i*])//it compare to right child
{
swap(m_vecData,i-,i*);
}
/*index*/
i=i*;
}
else if(i*+<=m_iHeapSize && m_vecData[i-]>m_vecData[i*])//it compare to right child
{
swap(m_vecData,i-,i*);
i=i*+;
}
else
{
break;
}
}
}
删除元素:pop(int index)
- 把堆的第index个元素删除,并把堆的最后一个元素放到index处。
- 把堆的第index个元素下沉
template <typename T>
bool MyMinHeap<T>::pop(int index)
{
if(isEmpty())
return false;
m_vecData[index]=m_vecData[m_iHeapSize-];
m_iHeapSize--;
sink(index+); return true;
}
数据结构-堆 C与C++的实现的更多相关文章
- 基本数据结构——堆(Heap)的基本概念及其操作
基本数据结构――堆的基本概念及其操作 小广告:福建安溪一中在线评测系统 Online Judge 在我刚听到堆这个名词的时候,我认为它是一堆东西的集合... 但其实吧它是利用完全二叉树的结构来维护一组 ...
- 数据结构-堆 Java实现
数据结构-堆 Java实现. 实现堆自动增长 /** * 数据结构-堆. 自动增长 * */ public class Heap<T extends Comparable> { priva ...
- C 数据结构堆
引言 - 数据结构堆 堆结构都很耳熟, 从堆排序到优先级队列, 我们总会看见它的身影. 相关的资料太多了, 堆 - https://zh.wikipedia.org/wiki/%E5%A0%86%E7 ...
- java数据结构----堆
1.堆:堆是一种树,由它实现的优先级队列的插入和删除的时间复杂度都是O(logn),用堆实现的优先级队列虽然和数组实现相比较删除慢了些,但插入的时间快的多了.当速度很重要且有很多插入操作时,可以选择堆 ...
- 数据结构 - 堆(Heap)
数据结构 - 堆(Heap) 1.堆的定义 堆的形式满足完全二叉树的定义: 若 i < ceil(n/2) ,则节点i为分支节点,否则为叶子节点 叶子节点只可能在最大的两层出现,而最大层次上的叶 ...
- [数据结构]——堆(Heap)、堆排序和TopK
堆(heap),是一种特殊的数据结构.之所以特殊,因为堆的形象化是一个棵完全二叉树,并且满足任意节点始终不大于(或者不小于)左右子节点(有别于二叉搜索树Binary Search Tree).其中,前 ...
- 数据结构&堆&heap&priority_queue&实现
目录 什么是堆? 大根堆 小根堆 堆的操作 STL queue 什么是堆? 堆是一种数据结构,可以用来实现优先队列 大根堆 大根堆,顾名思义就是根节点最大.我们先用小根堆的建堆过程学习堆的思想. 小根 ...
- 基本数据结构 —— 堆以及堆排序(C++实现)
目录 什么是堆 堆的存储 堆的操作 结构体定义 判断是否为空 往堆中插入元素 从堆中删除元素 取出堆中最大的元素 堆排序 测试代码 例题 参考资料 什么是堆 堆(英语:heap)是计算机科学中一类特殊 ...
- 数据结构——堆(Heap)大根堆、小根堆
目录 Heap是一种数据结构具有以下的特点: 1)完全二叉树: 2)heap中存储的值是偏序: Min-heap: 父节点的值小于或等于子节点的值: Max-heap: 父节点的值大于或等于子节点的值 ...
- 第二十八篇 玩转数据结构——堆(Heap)和有优先队列(Priority Queue)
1.. 优先队列(Priority Queue) 优先队列与普通队列的区别:普通队列遵循先进先出的原则:优先队列的出队顺序与入队顺序无关,与优先级相关. 优先队列可以使用队列的接口,只是在 ...
随机推荐
- D02 TED Elon Mulsk The future we're building — and boring
摘要:精选TED. 每个音频不超过2分钟,学英语和吸收伟大思想两不误 音频: https://n1audio.hjfile.cn/st/de745862-d5f4-4ef4-9218-d79361ca ...
- 询问Spring Bott和高并发框架两个问题
这里我问两个问题,请大神告诉我. 第一个问题,如果我想用Spring Boot开发企业级的微服务,我该看哪些资料?比如数据库该如何配置?消息中间件该怎么设置?等等.或者可以推荐给我几本这方面的书. 第 ...
- ABP入门系列(12)——如何升级Abp并调试源码
ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 1. 升级Abp 本系列教程是基于Abp V1.0版本,现在Abp版本已经升级至V1.4.2(截至 ...
- mysql千万级数据表,创建表及字段扩展的几条建议
一:概述 当我们设计一个系统时,需要考虑到系统的运行一段时间后,表里数据量大约有多少,如果在初期,就能估算到某几张表数据量非常庞大时(比如聊天消息表),就要把表创建好,这篇文章从创建表,增加数据,以及 ...
- 有关Ajax跨域请求的解决方案
前言 最近博主在赶项目进度.所以微信二次开发那边的博文一直没有更新.后续时间会慢慢记录这个学习历程的.来年公司要开发微信小程序.到时也会记录一下历程. 闲话少说,今天在工作中遇到了SpringMVC接 ...
- SQLMap安装步骤
SQLMap是利用Python语言写的,所以需要将Python这个语言环境给安装上 : 1.首先下载Python(这里Python版本为2.7.2,可以下载不同或高版本的) 2.然后在下载sqlmap ...
- spring boot + Thymeleaf开发web项目
"Spring boot非常适合Web应用程序开发.您可以轻松创建自包含的HTTP应用.web服务器采用嵌入式Tomcat,或者Jetty等.大多数情况下Web应用程序将使用 spring- ...
- Docker(十二):Docker集群管理之Compose
1.Compose安装 curl -L https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname ...
- Fragment生命周期及实现点击导航图片切换fragment,Demo
PS:Fragment简介 Fragment是Android3.0后引入的一个新的API,他出现的初衷是为了适应大屏幕的平板电脑, 当然现在他仍然是平板APP UI设计的宠儿,而且我们普通手机开发也会 ...
- Linux根目录详解-转自鸟哥的私房菜
转自:http://myhat.blog.51cto.com/391263/107931/ *根目录(/)的意义与内容: 根目录是整个系统最重要的一个目录,因为不但所有的目录都是由根目录衍生出来的 ...