最小堆,堆排序(c++代码)
来源:互联网 发布:mysql in exists 性能 编辑:程序博客网 时间:2024/06/16 17:42
//所谓的最大堆,最小堆其实是一颗完全二叉树.并以数组来存储树的节点元素.这里的示例从数组的0下标开始存储树的节点.//最小堆的父节点<=子节点,最大堆的父节点>=子节点.//最大堆常用于实现优先队列等,最小堆常用于实现定时器(例如libevent)等.//以下代码实现了最小堆和堆排序的算法,作为备忘笔记.使用的时候可以封装成模板类,这里只是算法的示例代码.//从大到小排序使用最小堆,从小到大排序使用最大堆.//要改成最大堆只需要改几个(<=)运算符.//如有错误,欢迎指正.#include <stdlib.h>#include <stdio.h>#include <vector>#define HEAP_PARENT(i)((i-1)/2)#define HEAP_LEFTCHILD(i)(2*i+1)#define HEAP_RIGHTCHILD(i)(2*i+2)using namespace std;//节点struct HeapNode{HeapNode(int k) : key(k){} int key;};//struct Heap{ Heap():size_(0) {} vector<HeapNode*>vec_; int size_;};//下移pos位置节点.//如果pos位置的节点 > 其子节点,则将pos位置元素和其子节点中较小的节点交换.并重复此过程,直到不能再下移.void shiftDown( Heap & h , int pos ) { int last_index = h.size_ - 1; while (1){ //叶节点,下移结束 bool has_child = HEAP_LEFTCHILD(pos) <= last_index ? true : false; if ( !has_child ) break; //找到父子三个节点中最小节点的位置 int min_index; min_index = h.vec_[pos]->key <= h.vec_[HEAP_LEFTCHILD(pos)]->key ? pos : HEAP_LEFTCHILD(pos); bool has_right_child = HEAP_RIGHTCHILD(pos) <= last_index ? true : false; if (has_right_child){ min_index = h.vec_[min_index]->key <= h.vec_[HEAP_RIGHTCHILD(pos)]->key ? min_index : HEAP_RIGHTCHILD(pos); } //如果父节点不是最小则和最小的子节点交换位置 if ( pos == min_index) break; //交换节点数据,更新pos,进行下一轮下移. HeapNode * temp = h.vec_[ pos ]; h.vec_[ pos ] = h.vec_[ min_index ]; h.vec_[ min_index ] = temp; pos = min_index; }}//上移pos位置节点.//如果pos位置的节点小于父节点,则和父节点交换.并重复此过程,直到不能再上移.void shiftUp( Heap & h , int pos ){ while ( pos > 0) { int parent = HEAP_PARENT(pos); if ( h.vec_[parent]->key <= h.vec_[pos]->key) break; // HeapNode * temp = h.vec_[pos]; h.vec_[pos] = h.vec_[parent]; h.vec_[parent] = temp; pos = parent; }}//将新节点加入到最后,并且上移该节点到适当位置.void push( Heap & h , HeapNode * newNode ){ int pos = h.size_; h.vec_.push_back(newNode); h.size_++; shiftUp(h , pos);}//将第一个节点与最后一个节点交换,再删除最后一个节点,从而弹出树顶端的节点.//将交换后的第一个节点下移到适当位置.HeapNode * pop(Heap & h){ if ( h.size_ == 0 ) return NULL; HeapNode * res = h.vec_[0]; h.vec_[0] = h.vec_[ h.size_ - 1 ]; h.vec_.pop_back(); h.size_--; shiftDown( h , 0 ); return res;}//建堆//从最后一个非叶子节点开始下移.直到根节点下移.将无序的数组创建为一个最小堆.void makeHeap(Heap & h){ for (int i = h.size_/2 - 1 ; i >= 0 ; i--){ shiftDown(h , i); }}//堆排序//由于最小堆的树顶元素为最小值,将树顶元素与最后一个元素交换,并且减小堆的大小.然后维护堆的性质.//等到树中只剩下一个元素的时候,存储堆的数组就是一个有序的序列.void heapSort(Heap & h){ for( int i = h.size_ - 1 ; i>=1 ; i-- ){ // HeapNode * temp = h.vec_[i]; h.vec_[i] = h.vec_[0]; h.vec_[0] = temp; h.size_--; // shiftDown(h , 0); }}void print_vec( Heap & h ){ for (int i = 0 ; i < h.vec_.size() ; i++){ printf("%d " , h.vec_[i]->key); }}#if 0int main(){ Heap h; HeapNode * node; printf("\n=====push , pop=======\n"); push(h , new HeapNode(100) ); push(h , new HeapNode(88) ); push(h , new HeapNode(89) ); push(h , new HeapNode(111) ); push(h , new HeapNode(60) ); while( (node = pop(h)) != NULL ){ printf( "%d " , node->key ); } printf("\n=====make heap , pop=======\n"); h.vec_.push_back( new HeapNode(100) ); h.vec_.push_back( new HeapNode(88) ); h.vec_.push_back( new HeapNode(89) ); h.vec_.push_back( new HeapNode(111) ); h.vec_.push_back( new HeapNode(60) ); h.size_ = 5; makeHeap(h); while( (node = pop(h)) != NULL ){ printf( "%d " , node->key ); } printf("\n=====make heap , heap sort=======\n"); h.vec_.push_back( new HeapNode(100) ); h.vec_.push_back( new HeapNode(88) ); h.vec_.push_back( new HeapNode(89) ); h.vec_.push_back( new HeapNode(111) ); h.vec_.push_back( new HeapNode(60) ); h.size_ = 5; makeHeap(h); heapSort(h); print_vec(h);}#endif
0 0
- 最小堆,堆排序(c++代码)
- java 堆排序代码(最小堆)
- 堆排序 - 最小堆
- 堆排序 纯C代码
- 堆排序C语言代码
- 最小堆和堆排序
- 堆排序(最小堆)
- 堆排序之最小堆
- 最小堆及堆排序
- 最大堆、最小堆、堆排序
- 最大堆、最小堆、堆排序
- 堆排序:最大堆与最小堆
- 最小堆和最小堆排序
- 【最小堆】--排序 -- Timer 最小堆 举例
- 最小堆排序
- 最小堆排序法
- 最大/最小堆排序
- 最大最小堆排序
- 外网如何访问本地tomcat web服务器
- 第17周项目--
- 第17周项目2-引用作形参
- matlab跟C#对接
- 第17周项目4—日期结构体
- 最小堆,堆排序(c++代码)
- tomact配置多个地址 、多个项目
- dxgfd
- 服务器集群相关技术
- 64弹出窗体的使用&&“leak window”的错误的解决
- hostapd wpa_supplicant madwifi详细分析(五)——hostapd_global_run函数
- 代理技术和AOP
- 第十七周项目二:引用做形参:传地址值
- poj1804(归并排序求逆序数)