堆是一个完全二叉树说着近似完全的二叉树。
(b)储存结构
源码在SVN里面:
堆主要满足两个性质:
1.父节点一定小于(大于,大根堆)两个子节点的键值。
2.每个子节点都是一个二叉堆。
一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。
10 | 15 | 56 | 25 | 30 | 70 |
源码在SVN里面:
http://code.taobao.org/svn/algincpluspluss/trunk
堆实现封装:
#include <iostream>
#include <vector>
#include <math.h>
#include <time.h>
#define LEFT(x) 2*x+1
#define RIGHT(x) 2*x+2
#define PARENT(x) (x-1)/2
using namespace std;
template<class T>
class CHeap{
protected:
vector<T> m_ar;
virtual bool g_or_l(T a,T b){
if(a < b)
return 1;
else
return 0;
}
inline void heapswap(int a,int b){
if (a!=b)//用异或交换的前提条件,要交换的数不能相等,否则都为被置为0
{
m_ar[a]=m_ar[a] + m_ar[b];
m_ar[b]=m_ar[a] - m_ar[b];
m_ar[a]=m_ar[a] - m_ar[b];
}
}
void heapfix(int i){
int left = LEFT(i);//左孩子下标
int right = RIGHT(i);//右孩子下标
int largest = i;//初始化为节点本身
if (left<m_ar.size()&&g_or_l(m_ar[i],m_ar[left]))//左孩子存在且大于自己
largest = left;
if (right<m_ar.size()&&g_or_l(m_ar[largest],m_ar[right]))//右孩子存在且大于自己
largest = right;
if(largest == i)
return;
heapswap(largest,i);
return heapfix(largest);
}
public:
T remove(){
heapswap(0,m_ar.size()-1);
vector<int>::iterator iter = m_ar.end() - 1;
T relem = m_ar[0];
cout<<"relem="<<relem<<endl;
m_ar.erase(iter);
heapfix(0);
return relem;
}
void insert(T insert_elem){
m_ar.push_back(insert_elem);
int i =m_ar.size() - 1;
while (PARENT(i) >= 0&&i != 0){
if(g_or_l(m_ar[PARENT(i)],m_ar[i]))
{
heapswap(i,PARENT(i));
i = PARENT(i);
}
else
break;
}
}
void heapsort()
{
for(int i=(m_ar.size());i>=0;i--)
heapfix(m_ar,i);
}
void traheap()
{
int cr=0,linecnt=0;
for(vector<T>::iterator iter=m_ar.begin();iter!=m_ar.end();iter++)
{
cout<<(*iter)<<" ";
if((++cr)==(int)pow((double)2,(double(linecnt))))
{
cout<<endl;
cr=0;
++linecnt;
}
}
}
virtual void debug(){
cout<<"CHeap"<<endl;
}
};
//小根堆的实现template<class T>
class CHeapsr:public CHeap<T>{
private:
virtual bool g_or_l(T a,T b){
if(a < b)
return 1;
else
return 0;
}
public:
virtual void debug(){
cout<<"CHeapsr"<<endl;
}
};
未封装的实现:
#include <iostream>
#include <vector>
#include <math.h>
#include <time.h>
#define LEFT(x) 2*x+1
#define RIGHT(x) 2*x+2
#define PARENT(x) (x-1)/2
using namespace std;
template<class T>
class CHeap{
private:
vector<T> ar;
bool bigroot;
public:
};
inline bool g_or_l(int a,int b){
if(a < b)
return 1;
else
return 0;
}
inline void heapswap(vector<int>& ar,int a,int b){
ar[a]=ar[a]^ar[b];
ar[b]=ar[a]^ar[b];
ar[a]=ar[a]^ar[b];
}
void heapfix(vector<int>& ar,int i){
int left = LEFT(i);//左孩子下标
int right = RIGHT(i);//右孩子下标
int largest = i;//初始化为节点本身
if (left<m_ar.size()&&g_or_l(m_ar[i],m_ar[left]))//左孩子存在且大于自己
largest = left;
if (right<m_ar.size()&&g_or_l(m_ar[largest],m_ar[right]))//右孩子存在且大于自己
largest = right;
if(largest == i)
return;
heapswap(largest,i);
return heapfix(largest);
}
int remove(vector<int>& ar){
heapswap(ar,0,ar.size()-1);
vector<int>::iterator iter = ar.end() - 1;
int relem = (*iter);
ar.erase(iter);
heapfix(ar,0);
return relem;
}
void insert(vector<int>& ar,int insert_elem){
ar.push_back(insert_elem);
int i =ar.size() - 1;
while (PARENT(i) >= 0&&i != 0)
if(g_or_l(ar[PARENT(i)],ar[i]))
{
heapswap(ar,i,PARENT(i));
i = PARENT(i);
}
}
void heapsort(vector<int>& ar)
{
for(int i=(ar.size());i>=0;i--)
heapfix(ar,i);
}
int main(int argc, char *args[])
{
srand(time(NULL));
vector<int> ar;
for(int i =0;i<16;i++)
ar.push_back(rand()%32);
for(int i =0;i<16;i++)
cout<<ar[i]<<endl;
cout<<"==========>"<<endl;
heapsort(ar);
int cr =0;
int linecnt=0;
for(int i =0;i<16;i++){
cout<<ar[i]<<" ";
if((++cr)==(int)pow((double)2,(double(linecnt)))){
cout<<endl; cr=0;++linecnt;
}
}
cout<<endl<<"==========heapremove>"<<endl;
int rem = remove(ar);
cout<<"removed elem ="<<rem<<endl;
cr =0;
linecnt=0;
for(int i =0;i<ar.size();i++){
cout<<ar[i]<<" ";
if((++cr)==(int)pow((double)2,(double(linecnt)))){
cout<<endl; cr=0;++linecnt;
}
}
cout<<endl<<"==========heap insert>"<<endl;
insert(ar,100);
cr =0;
linecnt=0;
for(int i =0;i<ar.size();i++){
cout<<ar[i]<<" ";
if((++cr)==(int)pow((double)2,(double(linecnt)))){
cout<<endl; cr=0;++linecnt;
}
}
cout<<endl<<"==========>"<<endl;
return 0;
}