标签:堆排
1、堆
一种完全二叉树的线性表示方法;就是数组形式保存数据。
大堆:根(父)结点大于左右结点数据 ------->降序
小堆:根(父)结点小于左右结点 ------->升序
小堆如图:
小堆符合每个根(父)结点都比左右结点小!!!
堆的存储结构,就是一个线性表结构:
private: enum{HEAP_DEFAULT_SIZE = 10}; //默认数组空间为10 Type *heap; //堆的数组名称 int capacity; //堆空间大小 int size; //有效元素个数
2、小堆
根据一组无序的数字创建小堆--------->最后实现堆排!
C++中创建小堆,可以通过构造函数一次性创建;也可以调用插入函数创建小堆;
小堆:堆顶的数据最小。
一些方法的实现:
(1)、删除函数 作用:每次删除堆顶,拿最后一个元素放到堆顶,在向下调整成小堆,这样就成升序输出了;
bool remove(Type &v){ if(size == 0){ return false; } v = heap[0]; heap[0] = heap[size-1]; size--; siftDown(0, size-1); return true; }
(2)、插入函数 作用:向上构建小堆
bool insert(const Type &x){ if(size > capacity){ return false; } heap[size] = x; siftUp(size); size++; return true; }
(3)、一次向下调整函数 作用:向下构建小堆
void siftDown(int start, int end){ int i = start; int j = 2*i+1; Type tmp = heap[i]; while(j <= end){ if(j+1 <= end && heap[j] > heap[j+1]){ j = j+1; } if(tmp > heap[j]){ heap[i] = heap[j]; //要是写交换函数的话,太浪费内存空间!! }else{ break; } i = j; j = 2*i+1; } heap[i] = tmp; }
(4)、一次向上调整函数
void siftUp(int start){ int j = start; int i = (j-1)/2; //父结点,这里的求法要注意。 Type tmp = heap[j]; //保存的是要插入的数据 while(j > 0){ if(heap[i] > tmp){ heap[j] = heap[i]; }else{ break; } j = i; i = (j-1)/2; } heap[j] = tmp; }
小堆的完整程序:
#ifndef _MIN_HEAP_H_ #define _MIN_HEAP_H_ #include<iostream> using namespace std; template<typename Type> class MinHeap{ public: MinHeap(int sz = HEAP_DEFAULT_SIZE){ capacity = sz > HEAP_DEFAULT_SIZE ? sz : HEAP_DEFAULT_SIZE; heap = new Type[capacity]; size = 0; } MinHeap(Type ar[], int n){ capacity = n > HEAP_DEFAULT_SIZE ? n : HEAP_DEFAULT_SIZE; heap = new Type[capacity]; size = n; for(int i = 0; i < n; i++){ heap[i] = ar[i]; } int curPos = n/2 - 1; //从最后一个非叶子结点开始调整, while(curPos >= 0){ siftDown(curPos, n-1); curPos--; //一直调整到根结点 } } ~MinHeap(){ delete []heap; heap = NULL; capacity = size = 0; } public: bool remove(Type &v){ if(size == 0){ return false; } v = heap[0]; heap[0] = heap[size-1]; size--; siftDown(0, size-1); return true; } bool insert(const Type &x){ if(size > capacity){ return false; } heap[size] = x; siftUp(size); size++; return true; } void showHeap()const{ for(int i = 0; i < size; i++){ cout<<heap[i]<<" "; } cout<<endl; } protected: void siftDown(int start, int end){ int i = start; //父结点 int j = 2*i+1; //子节点(左孩子) Type tmp = heap[i]; while(j <= end){ if(j+1 <= end && heap[j] > heap[j+1]){ j = j+1; } if(tmp > heap[j]){ heap[i] = heap[j]; //要是写交换函数的话,太浪费内存空间!!采用了直接覆盖的方法。 }else{ break; } i = j; j = 2*i+1; } heap[i] = tmp; } void siftUp(int start){ int j = start; int i = (j-1)/2; //父结点,这里的求法要注意。 Type tmp = heap[j]; while(j > 0){ if(heap[i] > tmp){ heap[j] = heap[i]; }else{ break; } j = i; i = (j-1)/2; } heap[j] = tmp; } private: enum{HEAP_DEFAULT_SIZE = 10}; Type *heap; int capacity; int size; }; #endif
测试程序:
#include"minHeap.h" int main(void){ int ar[] = {53, 17, 78, 9, 45, 65, 87, 23,}; int n = sizeof(ar)/sizeof(int); int i; MinHeap<int> hp; //MinHeap<int> hp(ar, n); for(i = 0; i < n; i++){ hp.insert(ar[i]); } hp.showHeap(); int value; for(i = 0; i < n; i++){ hp.remove(value); cout<<value<<" "; } cout<<endl; return 0; }
测试结果:
3、大堆------->降序
思想和小堆差不多,具体也不再分析了;
代码如下:
#ifndef _MAX_HEAP_H_ #define _MAX_HEAP_H_ #include<iostream> using namespace std; template<typename Type> class MaxHeap{ public: MaxHeap(int sz = DEFAULT_HEAP_SIZE){ capacity = sz > DEFAULT_HEAP_SIZE ? sz : DEFAULT_HEAP_SIZE; heap = new Type[capacity]; size = 0; } MaxHeap(int ar[], int n){ capacity = n > DEFAULT_HEAP_SIZE ? n : DEFAULT_HEAP_SIZE; heap = new Type[capacity]; size = n; for(int i = 0; i < n; i++){ heap[i] = ar[i]; } int curPos = n/2-1; while(curPos >= 0){ siftDown(curPos, size-1); curPos--; } } ~MaxHeap(){} public: bool insert(const Type &x){ if(size > capacity){ return false; } heap[size] = x; siftUp(size); size++; return true; } void remove(int &value){ value = heap[0]; heap[0] = heap[size-1]; size--; siftDown(0, size-1); } void showHeap(){ for(int i = 0; i < size; i++){ cout<<heap[i]<<" "; } cout<<endl; } protected: void siftDown(int start, int end){ int i = start; int j = 2*i+1; int tmp = heap[i]; while(j <= end){ if(j+1 <= end && heap[j] < heap[j+1]){ j = j+1; } if(heap[j] > tmp){ heap[i] = heap[j]; }else{ break; } i = j; j = 2*i+1; } heap[i] = tmp; } void siftUp(int start){ int j = start; int i = (j-1)/2; Type tmp = heap[j]; while(j > 0){ if(heap[i] < tmp){ heap[j] = heap[i]; }else{ break; } j = i; i = (j-1)/2; } heap[j] = tmp; } private: enum{DEFAULT_HEAP_SIZE = 10}; Type *heap; int capacity; int size; }; #endif
测试代码:
#include"maxHeap.h" int main(void){ int ar[] = {23, 45, 12, 6, 4, 9, 33,}; int n = sizeof(ar)/sizeof(int); int i; MaxHeap<int> hp; for(i = 0; i < n; i++){ hp.insert(ar[i]); } hp.showHeap(); int value; for(i = 0; i < n; i++){ hp.remove(value); cout<<value<<" "; } cout<<endl; return 0; }
测试结果:
标签:堆排
原文地址:http://11596096.blog.51cto.com/11586096/1835842