一.Min_heap的建立
堆是一种数据结构,分为最大值堆和最小值堆;
堆的内部结构是一个完全二叉树;
最大值堆的根节点是树中最大的元素,而父节点比任意一个子节点都要大;
最小值堆的根节点是树中最小的元素,父节点比任意一个子节点都要小;
我们用以下数组为建堆的材料:int testH[]={24,63,23,47,232,46,12,57,24,74};
逻辑中,我们对数组的结构可以这样设计:
-----图有点错了,最后两个是8和9
我们要建立一个堆,最重要的是三点:初始化堆,堆内调整算法,插入/删除;
设节点的下标为i(i!=0),孩子为2*i,2*i+1.
如果heap[i]>min(heap[2*i],heap[2*i+1])则交换节点,然后调整比如heap[2*i]与其孩子heap[2*2*i],heap[2*2*i+1].
节点规则:heap[i]<heap[2*i],heap[i]<heap[2*i+1];
(1)初始化堆我们的思想是从一个最小单元开始排序,就是最后一个父节点开始向前排序,而父节点的父节点是重叠子问题,只要最后一个父节点是最优的结构,往上解最优的时候就会获得全局最优的解集。
(2)当我们调整一个节点的时候,我们只需要往那个交换的节点的子节点进行调整。最小堆的一个规则,最简单的结构到复杂的结构的特点都是唯一的,也就是父节点比任意一个子节点都小。例如:
我们要调整55这个节点,44,和46已经调整好了(从后往前调整),55>46>44,则交换55和44这两个节点。这是不必调整46和它的子节点,理由很简单,它是个稳定的结构,没有进行节点调整,所以程序不必理会,而交换的44节点的结构变换了,要向下调整。所以建堆的思路是:从父节点往前调整,每一次调整深度优先。
初始化算法:
//初始化 void inith(int *a) { for(int i=0;i<hlength;i++) { heap[i]=*(a+i); } cout<<endl; } //建立堆 void build() { for(int i=hlength/2;i>=0;i--) { down(i); } } //从上往下调整法 void down(int p) { int q=p*2; int a=heap[p]; while(q<hlength) { if(q<hlength && heap[q]>heap[q+1]) { q++; } if(heap[q]>=a) { break; } else{ heap[p]=heap[q]; p=q; q=p*2; } heap[p]=a; } }
代码虽然很简单,但是思路确实很烦躁,要理解每一步的关键
最后形成的堆是:
-------更新 2014-11-15 22:00
实现最小堆的目的:堆排序
堆排序可以对大量的数据进行查找top k 而不占用大量的内存,原因是不用把数据加载到内存中,读入-堆比较-调整堆,这个流程,只要维护一个最小堆,top k不在话下
思路:利用最小值堆找出海量数据的前 k个最大值,比堆顶小的数据舍弃,比堆顶大的数据则替换掉堆顶并且向下调整,最后找出top k
#include <iostream> #include "heap_sort_min.h" using namespace std; void main() { int test[]={34,22,145,23,2,35,155,3245,1341,345,889,536,567,3546,786,468,468,464,48,646}; //int testH[]={24,63,23,47,232,46,12,57,24,74}; inith(test); build(); for(int i=9;i<20;i++) HeapSort(test[i]); for(int i=0;i<10;i++) cout<<heap[i]<<" "; cout<<endl; }
/*堆排序模块*/ void HeapSort(int a) { if(a<heap[0]) return; heap[0]=a; down(0); }
二.指针queue
类似Java的数组队列,而我所称的数组队列并不是严格的FIFO规则,只是一个可增长的动态数组,而指针的细节在于替代了原始地址要释放空间,不然会造成内存泄露
/* 数组队列 */ int *array; int size=10; int capacity=0; void queue() { array=new int[10]; } void add(int data) { int *temp; int *at=array; if(capacity==size) { temp=new int[++size]; for(int i=0;i<capacity;i++) temp[i]=array[i]; temp[size-1]=data; array=temp; delete[] at; capacity++; }else{ array[capacity++]=data; } }
最后一句:人生在于不停地奋斗,没有妹子就要孤独地写代码
<!--EndFragment-->
相关推荐
6.6 heap算法:make_heap, pop_heap, push_heap, sort_heap 338 6.7 其它算法 338 6.7.1 单纯的数据处理 338 adjacent_find 343 count 344 count_if 344 find 345 find_if 345 find_end 345 find_first_of ...
1. **keep_min_heap**:调整最小堆,确保堆的性质(父节点的权值小于或等于子节点)。 2. **heap_insert**:向最小堆中插入新的元素。 3. **heap_extract_min**:从最小堆中删除并返回最小元素。 4. **print_it**:...
`min_max_heap.h`文件则是小大根交替堆的定义和实现,包括堆的构建、调整和操作函数。`studentInfo.h`可能包含了学生信息的结构体定义,如姓名、学号和成绩等,这些信息可能会被用作堆中的元素。`Double_Ended_...
1. 创建一个最小堆(Min Heap)或优先队列(Priority Queue),存储所有节点。 2. 将每个字符及其频率作为节点插入到最小堆中。 3. 取出堆顶的两个节点,创建一个新的内部节点,将其设置为这两个节点的父节点,新...
最小堆 Min-Heap 乘法逆元 Modular-Multiplicative-Inverse 仅支持单点修改的可持久化线段树(维护区间和值) Persistent-Segment-Tree(Sum) 试除法素数测试 Prime-Check(Naive) 线性的素数筛法 Prime-Sieve...
局部变量通常存储在堆栈(Stack)中,全局变量存储在静态区(Static Area),动态申请的数据存储在堆(Heap)中。 3. 队列与栈的区别: 队列(Queue)遵循先进先出(FIFO)原则,而栈(Stack)遵循后进先出(LIFO...
SeqQueue(int capacity = 100) : front(0), rear(0), capacity(capacity), queue(new Type[capacity]) {} ~SeqQueue() { delete[] queue; } bool IsEmpty() const { // 是否为空 return front == rear; } ...
* 最小堆(Min Heap):是一种特殊的堆,父节点的值小于或等于子节点的值。 排序算法 排序算法是将数据元素按照一定的顺序排列的过程。常见的排序算法包括冒泡排序、选择排序、插入排序、归并排序、快速排序等。 ...
2. **最小堆**(Min Heap):用于存储待扩展的节点,通过`MinHeapNode`结构体实现。结构体包含节点的当前费用`cc`、子树费用的下界`lcost`、从根节点到当前节点的路径`x[s]`、顶点最小出边费用和`rcost`以及指向下一...
链表是一种线性数据结构,其中的元素不是在内存中连续存储的,而是通过指针链接在一起。链表包括单向链表、双向链表等多种形式。 #### Heap(堆) 堆是一种特殊的树形数据结构,它满足以下性质:每个节点的值都大于...
2. **链表 (Linked List)**:由节点组成的数据结构,每个节点包含数据和指向下一个节点的指针。 3. **栈 (Stack)**:后进先出(LIFO)的数据结构,主要操作为压栈(push)和弹栈(pop)。 4. **队列 (Queue)**:先进先出...