堆排序以及用堆实现的优先队列
相对于静态的对排序,堆实现的优先队列多了向上调整操作,但减少了建堆的操作。堆的添加一般是添加到顺序数组末尾,然后向上调整;而删除一般是删除顺序数组第一个元素(即“最大”的元素),然后向下调整。
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <cassert>
#include <queue>
using namespace std;
#define RESET "\033[0m"
#define BLACK "\033[30m" /* Black */
#define RED "\033[31m" /* Red */
#define GREEN "\033[32m" /* Green */
#define YELLOW "\033[33m" /* Yellow */
#define BLUE "\033[34m" /* Blue */
#define MAGENTA "\033[35m" /* Magenta */
#define CYAN "\033[36m" /* Cyan */
#define WHITE "\033[37m" /* White */
#define BOLDBLACK "\033[1m\033[30m" /* Bold Black */
#define BOLDRED "\033[1m\033[31m" /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m" /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m" /* Bold White */
bool match(const int A[], const int B[], int n)
{
bool ret=true;
if (A==NULL && B==NULL) ret=true;
else if (A==NULL || B==NULL) ret=false;
else
{
for(int i=0;i<n;++i)
if (A[i]!=B[i]) ret=false;
}
if(ret)
cout<<GREEN<<"SUCCEEDED. ";
else
cerr<<RED<<"FAILED. ";
cout<<"A: {";
for(int i=0;i<n;++i)
cout<<A[i]<<',';
cout<<"}. B: {";
for(int i=0;i<n;++i)
cout<<B[i]<<',';
cout<<"}."<<RESET<<endl;;
return ret;
}
class max_heap
{
private:
inline int left_child(int p)
{
return 2*p+1;
}
inline int right_child(int p)
{
return 2*p+2;
}
void fix_down(int A[], int n, int p)
{
int l=left_child(p);
int r=right_child(p);
int mx=p;
if(l<n && A[l]>A[mx]) mx=l;
if(r<n && A[r]>A[mx]) mx=r;
if(mx!=p)
{
swap(A[mx],A[p]);
fix_down(A,n,mx);
}
}
void build_max_heap(int A[], int n)
{
for(int i=n/2-1;i>=0;--i)
fix_down(A,n,i);
}
public:
void heap_sort(int A[], int n)
{
if(A==NULL) return;
build_max_heap(A,n);
for(int i=n-1;i>=0;--i)
{
swap(A[0],A[i]);
fix_down(A,i,0);
}
}
void test()
{
cout<<"test begins..."<<endl;
int *A1=NULL;
int A2[]={1};
const int oA2[]={1};
int A3[]={5,4,3,2,1};
const int oA3[]={1,2,3,4,5};
int A4[]={1,2,3,3};
const int oA4[]={1,2,3,3};
int A5[]={};
const int oA5[]={};
heap_sort(A1,0);
match(A1,NULL,0);
heap_sort(A2,1);
match(A2,oA2,1);
heap_sort(A3,5);
match(A3,oA3,5);
heap_sort(A4,4);
match(A4,oA4,4);
heap_sort(A5,0);
match(A5,oA5,0);
for(int i=0;i<10;++i)
{
srand(time(NULL));
int *A=new int[i];
int *oA=new int[i];
for(int j=0;j<i;++j)
{
A[j]=rand()%10;
oA[j]=A[j];
}
heap_sort(A,i);
sort(oA,oA+i);
match(A,oA,i);
delete[] A;
delete[] oA;
}
cout<<"test ends..."<<endl;
}
};
template <typename T>
void pv(T a, int n)
{
for(int i=0;i<n;++i)
cout<<a[i]<<',';
cout<<endl;
}
template <typename T>
class m_priority_queue
{
private:
vector<T> data;
int size;
public:
m_priority_queue():size(0){}
void push(T x)
{
if (size<data.size())
data[++size]=x;
else
{
data.push_back(x);
++size;
}
fix_up(size-1);
}
void pop()
{
assert(size!=0);
swap(data[0],data[size-1]);
--size;
fix_down(0);
}
T top()
{
assert(size!=0);
return data[0];
}
void test()
{
cout<<"test begins..."<<endl;
srand(time(NULL));
for(int i=0;i<10;++i)
{
int *seq=new int[i];
int *pseq=new int[i];
int sum=0;
for(int j=0;j<i;++j)
{
seq[j]=rand()%10;
if(sum<=0 || rand()%1==0)
{
pseq[j]=1;
++sum;
}
else
{
pseq[j]=0;
--sum;
}
}
priority_queue<int> std_pq;
m_priority_queue<int> m_pq;
int *A=new int[i];
int *oA=new int[i];
int k=0;
for(int j=0;j<i;++j)
{
if(pseq[j]==1)
{
std_pq.push(seq[j]);
m_pq.push(seq[j]);
}
else
{
A[k]=m_pq.top();
oA[k++]=std_pq.top();
std_pq.pop();
m_pq.pop();
}
}
while(sum-->0)
{
A[k]=m_pq.top();
oA[k++]=std_pq.top();
std_pq.pop();
m_pq.pop();
}
match(A,oA,k);
delete[] A;
delete[] oA;
delete[] pseq;
delete[] seq;
}
cout<<"test ends..."<<endl;
}
private:
inline int parent(int c)
{
if (c==0) return -1;
else return (c-1)>>1;
}
inline int left_child(int p)
{
return (p<<1)+1;
}
inline int right_child(int p)
{
return (p<<1)+2;
}
void fix_up(int c)
{
int p=parent(c);
if(p>=0 && data[p]<data[c])
{
swap(data[p],data[c]);
fix_up(p);
}
}
void fix_down(int p)
{
int l=left_child(p);
int r=right_child(p);
int max_index=p;
if(l<size && data[l]>data[max_index]) max_index=l;
if(r<size && data[r]>data[max_index]) max_index=r;
if(max_index!=p)
{
swap(data[p],data[max_index]);
fix_down(max_index);
}
}
};
int main()
{
max_heap s;
s.test();
m_priority_queue<int> p;
p.test();
return 0;
}