您的位置:首页 > 其它

堆排序以及优先队列

2015-03-10 22:08 295 查看
算法导论中的堆排序。

主要的几个函数:

三个宏用来表示取父节点和左右子节点,算法导论讲的很详细实现很简单
#define PARENT(i)(i/2)
#define  LEFT(i)(2*i)
#define  RIGHT(i)(2*i+1)
class Numbersort
{
public:
Numbersort()
{
arry=NULL;
nmber=0;
}
~Numbersort()
{
if (arry!=NULL)
{
delete[]arry;
}
}

int copynumber(int *p,int n);//给arry赋值
void putout();///输出数组
void sortnumber();///顺序排序,检验排序的正确性,堆排序中不用
void max_heapify(int heap_size,int i);//对长度为heap_size的堆的节点进行最大堆排序,以维护当前节点以及子节点的最大堆性质
void build_max_heap();//调用max_heapify构建最大堆
void stack_sort();//对build_max_heap()构建好的最大堆进行排序
void increase_key(int i,int key);//将当前借点i的key增加key(不是增加到key)
void addnum(int newn);//增加newn到最大堆中

private:
int *arry;
int nmber;
int size_down;
};


函数int copynumber(int *p,int n)、void putout()和sortnumber()没啥好说的。


void Numbersort::max_heapify(int heap_size,int i)
{
int l=LEFT(i);
int r=RIGHT(i);
int largest=0;
//堆排序的顺序比在数组中的位置大1,所以排序的顺序都要减去1
if (l<=heap_size&&arry[l-1]>arry[i-1])
{
largest=l;

}
else
largest=i;
if (r<=heap_size&&arry[r-1]>arry[largest-1])
{
largest=r;
}
if (largest !=i)
{
int temp=arry[largest-1];
arry[largest-1]=arry[i-1];
arry[i-1]=temp;
max_heapify(heap_size,largest);//递归调用以保证父节点后的子节点是最大堆
}
}


void Numbersort::build_max_heap()
{
int heap_size=nmber;
int half_size=heap_size/2;//最大堆中的去掉叶节点的节点数
for (int i=half_size;i>0;i--)
{
max_heapify(nmber,i);//对每个父节点逐次调用最大堆

}
}


void Numbersort::stack_sort()
{

for (int i=size_down;i>1;i--)
{
int temp=arry[0];
int temp2=arry[i-1];
arry[i-1]=arry[0];
arry[0]=temp2;//将最大的arry[0]与还未排序的最后一个交换,则最后一个就排好了数
size_down--;//sizedown减1后,已经排序好的数就不再参与最大堆排序。
max_heapify(size_down,1);
putout();
}
}


addnum(int newn)将一个newn元素添加到末尾,然后

void Numbersort::addnum(int newn)
{
int *p=new int [++nmber];

for (int i=0;i<nmber-1;i++)
{
p[i]=arry[i];
}
if (arry!=NULL)
{
delete arry;
arry=new int[nmber];
for (int i=0;i<nmber-1;i++)
{
arry[i]=p[i];
}
delete p;
}
arry[nmber-1]=0;//将最后一个元素置为0,然后调用increase_key
increase_key(nmber,newn);
}


将最大堆的第i个元素增加key

void Numbersort::increase_key(int i,int key)
{

arry[i-1]+=key;
while(i>1&&arry[PARENT(i)-1]<arry[i-1])
{//如果父节点比子节点小,则交换数,再对父节点进行判断,递归父节点的父节点是否符合。
int temp=arry[PARENT(i)-1];
arry[PARENT(i)-1]=arry[i-1];
arry[i-1]=temp;
i=PARENT(i);
}
}


总结:算法很简单,但是实现的时候总是会出现一些小问题,解决的也很爽快,主要还是不够细心,没有在草稿纸上先画一下。

有时候感觉,算法都贴出来有点傻X,这么简单还贴。这是一种小小成就感在内心蒸腾~(-ิo-ิ)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: