标题:堆排序的实现
只看楼主
没事跳楼耍
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2007-3-19
 问题点数:0 回复次数:13 
堆排序的实现

heap_sort()这个函数不知道有什么问题,堆的性质维护和建堆的函数都调试过了,没问题

以下是部分代码,红色部分请大家重点为我看看
//---------------------------------------------------------------------------
//最大堆类的声明
#ifndef MaxheapH
#define MaxheapH
#include"array.h"
class max_heap{
private:
array data;//数据数组
size_t heap_size;//堆的大小
size_t parent(long i);//返回第i个元素的父亲
size_t left(long i);//返回第i个元素的左孩子
size_t right(long i);//返回第i个元素的右孩子
public:
void heapify(int i);//堆的性质维护
max_heap(){};//缺省的构造函数
max_heap(array &a);//用数组a创建一个最大堆
int maximum();//返回最大值
int extract_max();//返回最大值且从堆中删除
void increase_key(int i,int key);//将第i个元素的键值增加为key
void insert(int key);//将键值key插入到堆中
void swap(size_t i,size_t j);//交换data[i],data[j]
void reduce();//对规模缩小1
};
//---------------------------------------------------------------------------
#endif

#include"maxheap.h"
size_t max_heap::parent(long i)//计算节点i的父节点下标
{ if(i%2)
return i/2;
else
return i/2+1;
}
size_t max_heap::left(long i){//计算节点i的左孩子节点下标
return 2*i+1;
}
size_t max_heap::right(long i){//计算节点i的右孩子节点下标
return 2*(i+1);
}
int max_heap::maximum(){//返回堆中最大元素值
return this->data[0];
}
int max_heap::extract_max(){//返回堆中最大元素值并将其在堆中删除
int max=-1;
if(this->heap_size>=1){
max=this->data[0];
this->data[0]=this->data[this->heap_size-1];
this->heap_size--;
this->heapify(0);
}
return max;
}
void max_heap::increase_key(int i,int key){//将节点i的值改变为key
if(key>this->data[i]){
this->data[i]=key;
while(i>0&&this->data[this->parent(i)]<this->data[i]){
this->swap(i/2,i);
i/=2;
}
}
}
void max_heap::insert(int key){//将值为key的节点插入到堆中
this->data[(this->heap_size)++]=-numeric_limits<int>::max();
increase_key(this->heap_size,key);
}
void max_heap::swap(size_t i,size_t j){//交换堆中两个节点的值
int temp;
temp=this->data[i];
this->data[i]=this->data[j];
this->data[j]=temp;
}
void max_heap::reduce(){//减少堆的大小
this->heap_size--;
}
void max_heap::heapify(int i){//对性质的维护
int l,r,largest;
l=this->left(i);
r=this->right(i);
if((l<=this->heap_size)&&(this->data[i]<this->data[l]))
largest=l;
else
largest=i;
if((r<=this->heap_size)&&(this->data[r]>this->data[largest]))
largest=r;
if(largest!=i){
this->swap(largest,i);
this->heapify(largest);
}
}
max_heap::max_heap(array &a){//创建堆
int i;
this->data=a;
size_t n=this->heap_size=a.size();
for(i=n/2-1;i>=0;i--)
this->heapify(i);
//for(i=0;i<n;i++)
// cout<<this->data[i]<<",";
//cout<<endl;
}


void heap_sort(array& a){
max_heap b(a);
int i,n=a.size();
for(i=n-1;i>=0;i--){
a[i]=b.maximum();//将堆b中的最大元素拷贝到a[i]
if(i>0){
b.swap(0,i);//将堆b中的根与最后一片叶子交换
b.reduce();//将堆b缩小
b.heapify(0);//对b维护堆性质
}
}
}


void main(){
array a;
fill_array(a,1000,10);//填充一个具有10个元素的数组
cout<<"排序前:"<<a<<endl;//输出排序前的数组
heap_sort(a);//排序
cout<<"排序后:"<<a<<endl;//输出排序后的数组
//max_heap b(a);
}


搜索更多相关主题的帖子: heap array size long 函数 
2007-10-12 20:49
aipb2007
Rank: 8Rank: 8
来 自:CQU
等 级:贵宾
威 望:40
帖 子:2879
专家分:7
注 册:2007-3-18
得分:0 

如果你其他堆的函数正确,那么单看heap_sort是没什么问题的。

也有可能你的array有问题,

结果是哪里不对,你说说清楚看!


Fight  to win  or  die...
2007-10-12 21:53
没事跳楼耍
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2007-3-19
得分:0 

我给个运行的结果:

排序前:655,262,743,805,365,171,631,120,44,595
排序后:595,595,262,595,365,595,631,655,743,805
Press any key to continue


请斑竹帮忙看看建堆和维持的函数,我输出建的堆看这两个函数是没问题的

[此贴子已经被作者于2007-10-12 22:28:33编辑过]

2007-10-12 22:24
永夜的极光
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:2721
专家分:1
注 册:2007-10-9
得分:0 

我写的一个堆排序,参考一下

程序代码:

#define UP(x) ((x-1)/2)
#define LEFT(x) ((x*2)+1)
#define RIGHT(x) ((x+1)*2)

void Heapify(int a[],int HeapSize,int i)
{
int l=LEFT(i),r=RIGHT(i),largest;
if(l<HeapSize && a[l]>a[i])
largest=l;
else
largest=i;
if(r<HeapSize && a[r]>a[largest])
largest=r;
if(largest!=i)
{
int tmp=a[largest];
a[largest]=a[i];
a[i]=tmp;

Heapify(a,HeapSize,largest);
}
}

void BuildHeap(int a[],int n)
{
int i;
for(i=n/2-1;i>=0;i--)
Heapify(a,n,i);
}

void HeapSort(int a[],int n)
{
int i,HeapSize=n;
BuildHeap(a,n);
for(i=n-1;i>0;i--)
{
int tmp=a[0];
a[0]=a[i];
a[i]=tmp;

HeapSize--;
Heapify(a,HeapSize,0);
}
}


从BFS(Breadth First Study)到DFS(Depth First Study)
2007-10-12 22:32
aipb2007
Rank: 8Rank: 8
来 自:CQU
等 级:贵宾
威 望:40
帖 子:2879
专家分:7
注 册:2007-3-18
得分:0 
if((l<=this->heap_size)&&(this->data[i]<this->data[l]))

if((r<=this->heap_size)&&(this->data[r]>this->data[largest]))

l和r都应该取不到heap_size吧

Fight  to win  or  die...
2007-10-12 22:34
没事跳楼耍
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2007-3-19
得分:0 
回复:(永夜的极光)我写的一个堆排序,参考一下[cod...

谢谢啊。

2007-10-12 22:42
没事跳楼耍
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2007-3-19
得分:0 
回复:(aipb2007) if((lheap_size)&...

斑竹真厉害

原来是我没注意,改过来就好了

2007-10-12 22:43
aipb2007
Rank: 8Rank: 8
来 自:CQU
等 级:贵宾
威 望:40
帖 子:2879
专家分:7
注 册:2007-3-18
得分:0 
写代码在判断上经常出错是因为边界和0值,多注意就好。

Fight  to win  or  die...
2007-10-12 22:45
aipb2007
Rank: 8Rank: 8
来 自:CQU
等 级:贵宾
威 望:40
帖 子:2879
专家分:7
注 册:2007-3-18
得分:0 
随便引申一个问题,这也是我最近写一个优先级队列模版时遇到的。

increase_key(int i,int key){//将节点i的值改变为key

这个操作,参数i表示堆中第i个元素,这里也就是data[i]

我的问题是,实际在用户使用这个接口时,他不会在意第i个元素在堆中是什么,因为那时我们封装的实现机制。
用户想改变一个元素的key值,最直接的是来自原始输入,举个例子:
输入 5 3 4 6 9
某一时刻堆中,也就是data中是9 5 3 4 6
用户要修改5为7的话,最直接的是increase_key(5,7),或者increase_key(0,7)
其中后者是原始输入的顺序号,然而对data中5的位置1是不可见,也是不必要知道的。

我的问题是任何按最直观的方式去定位这个待修改的元素。


————————————————————————
ps : 表达清楚没,不知!

Fight  to win  or  die...
2007-10-12 22:59
nuciewth
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:我爱龙龙
等 级:贵宾
威 望:104
帖 子:9786
专家分:208
注 册:2006-5-23
得分:0 
表达错误吧.
这个操作,参数i表示堆中第i个元素,这里也就是data[i]
都可以确定下标(参数就是下标),那修改还有什么难的.

可能是我没弄明白你的意思吧.

倚天照海花无数,流水高山心自知。
2007-10-13 00:12



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-177146-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.192885 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved