标签:堆排
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