| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1289 人关注过本帖
标题:堆排序
只看楼主 加入收藏
sunyh1999
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:14
帖 子:1178
专家分:3032
注 册:2009-5-17
结帖率:79.37%
收藏
已结贴  问题点数:20 回复次数:17 
堆排序
在百度上找了一个代码,自己改了一下,但是这个sift函数感觉是不很明白,请各位高手注释一下。
#include <stdio.h>
#include <stdlib.h>
void sift(int i,int m,int number[])
{
 int k=2*i,temp;
 temp=number[i];
 while(k<=m)
 {
 if(k<m&&number[k]<number[k+1])
 k++;
 if(k<=m&&temp<number[k])
 {
  number[i]=number[k];
  i=k;
  k=2*i;
 }
 else
 k=m+1;
 }
 number[i]=temp;
}
void heap_sort(int number[],int n)
{
 int i,temp=0;
 for(i=n/2;i>=0;i--)
 sift(i,n,number);
 for(i=n-1;i>=0;i--)
 {
  temp=number[i];
  number[i]=number[0];
  number[0]=temp;
  sift(0,i-1,number);
 }
}
int main()
{
 int i,number[10]={0},n;
 scanf("%d",&n);
 for(i=0;i<n;i++)
 scanf("%d",&number[i]);
 heap_sort(number,n);
 for(i=0;i<n;i++)
 printf("%d ",number[i]);
 system("pause");
 return 0;
}
搜索更多相关主题的帖子: 百度 
2011-01-26 11:08
sunyh1999
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:14
帖 子:1178
专家分:3032
注 册:2009-5-17
收藏
得分:0 
参考资料:http://baike.

欢迎来到我的博客:http://blog..cn/noisunyuhong
2011-01-26 11:33
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
收藏
得分:0 
百度 找的代码能叫代码吗 ?

我就是真命天子,顺我者生,逆我者死!
2011-01-26 13:13
baobaoisme
Rank: 7Rank: 7Rank: 7
来 自:AVATAR
等 级:黑侠
帖 子:260
专家分:506
注 册:2010-7-9
收藏
得分:5 
详见数据结构排序部分,应该是个数据结构的书都有
2011-01-26 14:54
犬虫门心
Rank: 8Rank: 8
来 自:西安
等 级:蝙蝠侠
帖 子:209
专家分:753
注 册:2011-1-25
收藏
得分:15 
void sift(int i,int m,int number[])
//i是完全二叉树(堆)中,当前要处理的节点编号
//m是当前要处理的堆中的元素个数
//number是堆本身
//根据下面主调函数的实参,可以知道,i的值应该是长度为m的完全二叉树中的最后一个非叶子节点的编号
{
int k=2*i/*根据完全二叉树的性质,编号为i的节点的做孩子的编号应该是2*i,那么k就是i节点的左孩子节点*/,temp;
temp=number[i];//保存当前节点的值,有可能覆盖
while(k<=m)//如果还有中间节点没有处理完
{
if(k<m&&number[k]<number[k+1])//number[k]和number[k+1]分别是number[i]的左、右孩子,这是在找值最大的孩子
k++;
if(k<=m&&temp<number[k])//如果孩子比其父节点的值都大的化,则覆盖父节点的值,看来这是要形成“大根堆”
{
  number[i]=number[k];
  i=k;//让节点指针移动到值交换之后的子节点处
  k=2*i;//k依然指向i的左孩子节点
}
else
k=m+1;//如果没有交换,即number[i]、number[k]和number[k+1]所构成的堆本身满足大根堆,则不需要再向下继续了
}
number[i]=temp;//将函数一开始要移动的number[i]的值,移动到现在(可能移动、也可能没有移动)的number[i]里
}
其实这个函数应该是“大根堆”调整函数

当一名对得起学生学费的老师,一直是我的目标!我会更努力的!
2011-01-26 16:36
sunyh1999
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:14
帖 子:1178
专家分:3032
注 册:2009-5-17
收藏
得分:0 
非常感谢楼上!
问几个小问题:
在这个程序中有几个地方可以改成我注释的部分吗?为什么?
#include <stdio.h>
#include <stdlib.h>
void sift(int startPos,int endPos,int number[])
{
 int k=2*startPos,temp;
 temp=number[startPos];
 while(k<=endPos)
 {
 if(k<endPos&&number[k]<number[k+1]) k++;
 if(k<=endPos&&temp<number[k])//k<=endPos   可以删去吗?
 {
  number[startPos]=number[k];
  startPos=k;
  k=2*startPos;
 }
 else
 k=endPos+1;//将这句删去,换为break
 }
 number[startPos]=temp;
}
void heap_sort(int number[],int n)
{
 int i,temp=0;
 for(i=n/2;i>=0;i--)
 sift(i,n,number);
 for(i=n-1;i>=0;i--)
 {
  temp=number[i];
  number[i]=number[0];
  number[0]=temp;
  sift(0,i-1,number);
 }
}
int main()
{
 int i,number[10]={0},n;
 scanf("%d",&n);
 for(i=0;i<n;i++)
 scanf("%d",&number[i]);
 heap_sort(number,n);
 for(i=0;i<n;i++)
 printf("%d ",number[i]);
 system("pause");
 return 0;
}

欢迎来到我的博客:http://blog..cn/noisunyuhong
2011-01-26 19:08
merrydanae
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2011-1-26
收藏
得分:0 
这个是要什么级别才可以看懂,我是初学者,咋看那不懂
2011-01-26 19:16
犬虫门心
Rank: 8Rank: 8
来 自:西安
等 级:蝙蝠侠
帖 子:209
专家分:753
注 册:2011-1-25
收藏
得分:0 
#include <stdio.h>
#include <stdlib.h>
void sift(int startPos,int endPos,int number[])
{
int k=2*startPos,temp;
temp=number[startPos];
while(k<=endPos)
{
if(k<endPos&&number[k]<number[k+1]) k++;
if(k<=endPos&&temp<number[k])//k<=endPos   可以删去吗?
/****************************************************************/
严格的说,这里有些乱!如果不强求细节(不要执行,只是表达理论,这是国内教材的一贯伎俩)的话,无所谓了。
但如果严格些,这个程序压根就有大问题!
堆(完全二叉树的连续存储结构)存在这样的结论:
若s[i]节点有孩子,那么,其左孩子为s[i*2],右孩子为s[i*2+1];且如果s[i]只有一个孩子,那么只能是左孩子,且s[i]一定是最后一个非叶子节点。
但上述表达式成立的大前提是:s[]数组的下标得从1开始,而不是0!
C语言的下标从0开始,那么,这个下标关系就必须改成:
父节点下标:i
左孩子下标:i*2+1
右孩子下标:i*2+2
很纠结吧!
哈哈哈哈
{
  number[startPos]=number[k];
  startPos=k;
  k=2*startPos;
}
else
k=endPos+1;//将这句删去,换为break
/*************************************************************/
可以的,当然是可以的。不过从软件工程的角度来看,这违反了模块的单入单出原则。
}
number[startPos]=temp;
}
void heap_sort(int number[],int n)
{
int i,temp=0;
for(i=n/2;i>=0;i--)
sift(i,n,number);
for(i=n-1;i>=0;i--)
{
  temp=number[i];
  number[i]=number[0];
  number[0]=temp;
  sift(0,i-1,number);
}
}
int main()
{
int i,number[10]={0},n;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&number[i]);
heap_sort(number,n);
for(i=0;i<n;i++)
printf("%d ",number[i]);
system("pause");
return 0;
}

[ 本帖最后由 犬虫门心 于 2011-1-26 19:26 编辑 ]

当一名对得起学生学费的老师,一直是我的目标!我会更努力的!
2011-01-26 19:25
点线面
Rank: 8Rank: 8
来 自:NO.-1
等 级:蝙蝠侠
帖 子:525
专家分:980
注 册:2011-1-3
收藏
得分:0 
这个单纯写注释还是难明白,毕如结合图形表示,不然很难明白。

小代码,大智慧
2011-01-26 19:41
犬虫门心
Rank: 8Rank: 8
来 自:西安
等 级:蝙蝠侠
帖 子:209
专家分:753
注 册:2011-1-25
收藏
得分:0 
也是,如果直接面对面听我边比划边讲,那是最清楚的了。

当一名对得起学生学费的老师,一直是我的目标!我会更努力的!
2011-01-26 19:44
快速回复:堆排序
数据加载中...
 
   



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

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