N个元素中找到两个最小元素的方法

darkstar21cn 2002-09-02 09:37:44
N个元素中找到两个最小元素的方法以及他的比较次数。
...全文
535 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
darkstar21cn 2002-09-15
  • 打赏
  • 举报
回复
谢谢saint001(saint001) 的理论知识,但大家应该都知道的.
darkstar21cn 2002-09-15
  • 打赏
  • 举报
回复
to zhangyilan(数字通信):数组是无序的.
dcyu 2002-09-07
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <stdlib.h>
#define INT_MAX 32767

int main()
{
int min,secmin;
int i,x,n;
max=INT_MAX;
secmax=INT_MAX;
printf("Total Num: ");
scanf("%d",&n);
if(n<1) return 1;
for(i=1;i<=n;i++)
{
scanf("%d",&x);
if(x<=min) {
secmin=min;
min=x; }
else {
if(x<=secmin) secmin=x;
else continue; }
}
printf("Min is %d. Secmin is %d. ",min,secmin);
return 0;
}

这是我过去发的贴子中改的,参考:
http://www.csdn.net/expert/topic/938/938945.xml?temp=.9978296
saint001 2002-09-06
  • 打赏
  • 举报
回复
败者树是外排算法
在许多实际应用系统中,经常遇到要对数据文件中的记录进行排序处理。由于文件中的记录很多、信息量庞大,整个文件所占据的存储单元远远超过一台计算机的内存容量。因此,无法把整个文件输入内存中进行排序。于是,就有必要研究适合于处理大型数据文件的排序技术。通常,这种排序往往需要借助于具有更大容量的外存设备才能完成。相对于仅用内存进行排序(又称为内排序)而言,这种排序方法就叫做外排序。在实际应用中,由于使用的外存设备不同,通常又可以分为磁盘文件排序和磁带文件排序两大类。磁带排序和磁盘排序的基本步骤相类似,它们的主要不同之处在于初始归并段在外存贮介质中的分布方式,磁盘是直接存取设备,磁带是顺序取设备。
  外部排序基本上由两个相对独立的阶段组成。首先,按可用内存大小,将外存上含n个记录的文件分成若干长度为h的子文件,依次读入内存并利用有效的内部排序方法对它们进行排序,并将排序后得到的有序子文件重新写入外存,通常称这些有序子文件为归并段或顺串;然后,对这些归并段进行逐趟归并,使归并段(有序的子文件)逐渐由小到大,直至得到整个有序文件为止。
  最简单的归并方法类似于内部排序中的二路归并算法。二路归并排序的方法,其基本思想就是:先把具有n个记录的文件看作是由n个长度为1的顺串构成的。在此基础上进行一趟又一趟的归并。一趟归并,是把文件中每一对长度为 h的顺串合并成一个长度为2h的顺串;其结果将使文件中顺串的长度增加一倍而使顺串的数量减少一半。经过若干趟归并之后,当文件中只含有一个长度为n的顺串时,整个文件的排序就完成了。
  还有一种常用的快速的多路归并法:多路归并排序。多路归并排序是二路归并排序的推广,它可以减少归并趟数,m 路归并排序的基本方法是:开始,把若干长度为K的初始顺串尽量均匀地分布到m个输入文件f1...,fm上。然后反复从f1,...,fm各读一个顺串,归并成长度为mk的顺串,轮流地写到输出文件g1,...,gm上。下一趟从g1,...,gm归并到f1,...,fm.一趟又趟地反复进行,直到排序结束。在进行多路归并时,需要从K个记录中选关键字最小的记录,为了不增加内部归并时需进行关键字比较的次数,在具体实现时,通常不用选择排序的方法,而用"败者树"来实现。又从外部的趟数[logkm]可见,若减少m也可减少外排的时间,对待排序的初始记录进行"置换选择排序"可以得到平均长度为2h的有序子序列。这些内容在此不予讨论,有兴趣者可参阅有关参考书。
Banned 2002-09-06
  • 打赏
  • 举报
回复
趋同gofor
树形选择排序

找出最小数实际上是初始化完全二叉树,
经过[N/2]次比较就能得到最小数;
然后把最小数改变成最大的数(就是比其他的数都大),
沿着叶子结点到根的路径上调整二叉树,得到一个最小数,
这个最小数是原来的次小数了,花时[logN],
于是[N/2]+[logN]<N
qiuyang_wang 2002-09-06
  • 打赏
  • 举报
回复
zhangyilan(数字通信) :你说的折半比较在特殊情况下可能会出现错误结果的。
o3y 2002-09-06
  • 打赏
  • 举报
回复
我觉得我们不如思考一个求第k小元素的算法,第二小元素的算法不太难,qiuyang_wang(小数点)的就可以了
zhangyilan 2002-09-06
  • 打赏
  • 举报
回复
折半比较吧
将数据的前1/2与后1/2的数据相应比较1/2次
较下的数放在前1/2
然后再折半比较1/4
。。。。。
royalier 2002-09-06
  • 打赏
  • 举报
回复

min,min2 为用来保存的N个数中的最小的两个。min是最小,min2为次小。

第一次读入前2个数,比较大的放在min2,小的放在min。
从3个数开始。与min2比较。大于的情况下,继续比较下一个。
小于的情况下,置换掉min2。然后min和min2比较。
Banned 2002-09-05
  • 打赏
  • 举报
回复
用最小堆来实现吧
如果用插入操作来构建初始化堆,可以在O(nlogn)的时间内完成
堆的初始化,即比较次数不超过nlogn;
堆初始化后最顶的元素就是最小的元素,
然后删掉最小元素后形成的新堆的最小元素就是原来的堆的
次小元素,删除的操作可以在O(logn)内完成。
于是求两个最小元素 的时间复杂度为
O(nlogn+logn)。
darkstar21cn 2002-09-05
  • 打赏
  • 举报
回复
up!
怎么没人理我了?
qiuyang_wang 2002-09-03
  • 打赏
  • 举报
回复
设定两个存储单元:N1,N2,N1中保存最小的两个中较大的一个,N2中保存最小的一个。
假设前两个数是最小的,比较这两个数,将小的放在N2中,大的放在N1中。
从第三个开始循环与N1比较,如果当前比较的值大于N1的值,则继续循环直到最后。如果当前比较的值小于N1的值,则与N2做比较,如果大于N2则用当前值替换N1的值,如果小于N2,则用N2的值替换N1的值,当前值替换N2的值。
这样做法应该是比较最少的了,最少比较:N-1次,最多比较:2N-3次。
darkstar21cn 2002-09-03
  • 打赏
  • 举报
回复
我想到一种方法:使用败者树,比较次数是——n/2+n/4……+2+1=?(好像是等于n吧?)
败者树就是两个数据比较时较大的元素作为他们的根节点,而较小的元素进行下一轮比较。
但不知是否对。清指点,谢谢!
KingPower410 2002-09-03
  • 打赏
  • 举报
回复
建立一棵二插树。取一个元素做根(root),也是比较的基点。然后取下一个元素与root比较,如果小于root的话,该元素做左子树的root,否则做右子树的root。依此递归下去,得到一个二叉树。用中序遍历得到的第一、第二的元素即是两个最小的元素了。
gofor 2002-09-02
  • 打赏
  • 举报
回复
树形选择排序。
找出最小数,N-1次比较
找出第二个最小数,logN次
Lawrence444 2002-09-02
  • 打赏
  • 举报
回复
直接找,2n-2次。
两个数排一下序,最坏2n-1次,平均时候要小的多。

33,006

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧