明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 4232|回复: 14

关于快速找出最小3个数的算法问题

  [复制链接]
发表于 2004-1-8 17:10:00 | 显示全部楼层 |阅读模式
本帖最后由 作者 于 2004-1-8 18:49:21 编辑

数组a(n)   (n>5000)
用什么办法快速找出最小3个值的数组下标 i1,i2,i3  ?(不改变数组a(n)的结构)
发表于 2004-1-8 17:38:00 | 显示全部楼层
不用排序就简单点,用逐个比较法,先将前三个数保存下来,记录位置,排序,如a1,a2,a3,其中a3为最小,然后后继的数就与这a3比较,如果比A3小,则替换A3,原A3替换A2,原A2替换A1。如果后继的数比A3大,比A2小,则替换A2,原A2替换A1。如果后继的数比A1小比A2大,则替换A1。
这样就行了。
 楼主| 发表于 2004-1-8 18:26:00 | 显示全部楼层
三个值好找,但三个值对应的下标不太好找,可以给一段代码吗
发表于 2004-1-8 18:27:00 | 显示全部楼层
用排序法比较好!
for i=1 to 4999
for j=i+1 to 5000
If x(i) > x(j) Then t = x(i): x(i) = x(j): x(j) = t
Next
Next
For i = 1 To 3
debug.Print x(i)
Next
 楼主| 发表于 2004-1-8 18:46:00 | 显示全部楼层
4楼的代码,好像只能找到值,而不能找到对应数组的下标,因为目的是找到最小三个值的下标,而且前提是我不能改变原来数组的值
发表于 2004-1-8 19:13:00 | 显示全部楼层
这类问题,属于数据结构方面的问题,只要看一看,数据结构方面关于排序查找这部分,折半,冒泡等算法只要根据你的题目的需要,都有一个满意的算法。我觉得这道题采用起泡法排序最好。
发表于 2004-1-8 19:19:00 | 显示全部楼层
先自定义一个数据类型。
如:
    type s
    index as interger
    num as integer
    end type
然后dim a(n) as s,根据a(i).num进行排序,只要找到最小的三个数,然后再就能找到它们的index,这样下标就能找到了.
不过这样比较费内存.
发表于 2004-1-8 19:21:00 | 显示全部楼层
其中的index为该数的下标,在程序运行中是不变的,num为该数的值
发表于 2004-1-8 19:35:00 | 显示全部楼层
这个不知道是否满足。


  1. Option Explicit

  2. ' 第2维:0索引,1值
  3. Dim b(0 To 3, 0 To 1) As Double

  4. Sub test()
  5.     ' 生成初始数据
  6.     Dim n As Integer
  7.     n = 5000
  8.     Dim a() As Double
  9.     ReDim a(0 To n)
  10.     Dim i As Integer
  11.     For i = 0 To n
  12.         a(i) = 1000 * Rnd
  13.     Next
  14.    
  15.     ' 赋值
  16.     b(0, 0) = 1
  17.     b(0, 1) = a(0)
  18.     b(1, 0) = 2
  19.     b(1, 1) = a(1)
  20.     b(2, 0) = 3
  21.     b(2, 1) = a(2)
  22.     ' 排序
  23.     MinEx 4, a(3)
  24.     Debug.Print b(0, 0) & ": " & b(0, 1)
  25.     Debug.Print b(1, 0) & ": " & b(1, 1)
  26.     Debug.Print b(2, 0) & ": " & b(2, 1)

  27.     ' 排序
  28.     For i = 4 To n
  29.         MinEx i, a(i)
  30.     Next
  31.     Debug.Print b(0, 0) & "," & b(0, 1)
  32.     Debug.Print b(1, 0) & "," & b(1, 1)
  33.     Debug.Print b(2, 0) & "," & b(2, 1)
  34. End Sub

  35. Sub MinEx(ByVal Index As Long, ByVal Value As Double)
  36.     b(3, 0) = Index ' 索引
  37.     b(3, 1) = Value ' 值
  38.    
  39.     ' 数组排序
  40.     Dim t As Double
  41.     Dim i As Integer
  42.     Dim j As Integer
  43.     For i = 0 To 2
  44.         For j = i + 1 To 3
  45.             If b(i, 1) > b(j, 1) Then
  46.                 t = b(i, 0)
  47.                 b(i, 0) = b(j, 0)
  48.                 b(j, 0) = t
  49.                 t = b(i, 1)
  50.                 b(i, 1) = b(j, 1)
  51.                 b(j, 1) = t
  52.             End If
  53.         Next
  54.     Next
  55. End Sub
发表于 2004-1-8 20:49:00 | 显示全部楼层

我的代码及运行测试结果


  1. '为了得到程序运行时间,所有中间数据都声明为Long长整型,程序忽略了错误处理代码
  2. Dim UserArray As Variant
  3. Private Sub InitialArray()   '初始化数组
  4.   Dim SizeOfArray As Long    '数组大小
  5. '当然我输入的是整数
  6.   SizeOfArray = CLng(ThisDrawing.Utility.GetString(False, "输入数组大小"))  
  7.   Randomize
  8.   ReDim UserArray(1 To SizeOfArray) As Long
  9.   Dim i As Long
  10.   For i = 1 To SizeOfArray
  11.     UserArray(i) = Int(1000000 * Rnd)   '随机填写长整数到数组中
  12.   Next i
  13.   MsgBox "数组初始化完成!"
  14. End Sub

  15. Private Sub Sort()
  16.   Dim m(1 To 3) As Long
  17.   m(1) = 1: m(2) = 2: m(3) = 3
  18.   '排序前三个数,代码可能不太好读,但效率高
  19.   Dim i As Long
  20.   If UserArray(m(1)) > UserArray(m(2)) Then t = m(1): m(1) = m(2): m(2) = t
  21.   If UserArray(m(1)) > UserArray(m(3)) Then t = m(1): m(1) = m(3): m(3) = t
  22.   If UserArray(m(2)) > UserArray(m(3)) Then t = m(2): m(2) = m(3): m(3) = t
  23.   '使用直接查找算法,仅一次循环
  24.   For i = 4 To UBound(UserArray)
  25.     If UserArray(i) <= UserArray(m(1)) Then
  26.       m(3) = m(2)
  27.       m(2) = m(1)
  28.       m(1) = i
  29.     ElseIf UserArray(i) <= UserArray(m(2)) Then
  30.       m(3) = m(2)
  31.       m(2) = i
  32.     ElseIf UserArray(i) <= UserArray(m(3)) Then
  33.       m(3) = i
  34.     End If
  35.   Next i
  36.   ThisDrawing.Utility.Prompt “最小值下标为:” & m(1)
  37.   ThisDrawing.Utility.Prompt “第二小值下标:” & m(2)
  38.   ThisDrawing.Utility.Prompt “第三小值下标:” & m(3)
  39. End Sub

另外,对于whyer朋友的一些说法给予纠正:
折半是查找算法,不是排序算法,并且它只能在已经排序的序列中查找,在这个问题中用不上。冒泡是一种非常低效率的排序算法,不宜做大量数据排序。
我的机器,以上代码在ACAD 2004内嵌的VBA中运行,数组大小在百万以下得不到运行时间,数组大小为一百万时耗时约0.05秒,五千万约3.45秒,一亿约6.94秒。(同时运行明经网站和VC.Net 2003)再大的数组(我试了五亿),我的虚拟内存不足。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-28 08:29 , Processed in 0.197092 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表