现在的位置: 首页 > 综合 > 正文

Visual FoxPro 的一个排序作业

2013年09月05日 ⁄ 综合 ⁄ 共 3968字 ⁄ 字号 评论关闭

     前段时间帮助一个同学完成了一道Visual FoxPro的排序算法作业题,在此记录一下。

 

一、题目要求:

        程序先要求使用者输入N个数,最后依次输出原始输入数列、从小到大排列后的数列、从大到小排列后的数列、两端大中间小排列后的数列。

二、程序代码:

  1. CLEAR
  2. NumCount = 0
  3. INPUT "   请输入需要排序的N个数:" to NumCount
  4. IF NumCount<1
  5.     ? "  输入的数据个数必须大于0!"
  6.     RETURN
  7. ENDIF
  8. DIME NumArr(NumCount)
  9. * Accept numbers from keyboard
  10. FOR i=1 TO NumCount
  11.     INPUT "   请输入第"+ALLTRIM( STR(i) )+"个数:" to NumArr(i)
  12. ENDFOR
  13. * Print Orginal numbers
  14. "   原始输入数列:"
  15. FOR i=1 TO NumCount
  16.     ?? ALLTRIM( STR( NumArr(i) ) ) + "  "
  17. ENDFOR
  18. * Sort the array
  19. FOR curIndex = 2 TO NumCount
  20.     curData         = NumArr( curIndex )
  21.     sortedMinIndex  = 1
  22.     sortedMaxIndex  = curIndex - 1                      
  23.     
  24.     * query the positon that the curData should put in
  25.     DO WHILE sortedMinIndex <= sortedMaxIndex
  26.         midIndex =  ( sortedMinIndex + sortedMaxIndex ) / 2
  27.         
  28.         IF NumArr( midIndex ) < curData
  29.             sortedMinIndex = sortedMinIndex + 1
  30.         ELSE
  31.             sortedMaxIndex = sortedMaxIndex - 1
  32.         ENDIF       
  33.     ENDDO
  34.     
  35.     *move data forward index from sortedMinIndex
  36.     FOR j = curIndex - 1 TO sortedMinIndex STEP -1
  37.         NumArr( j+1 ) = NumArr( j ) 
  38.     ENDFOR
  39.     
  40.     * put curData to its position
  41.     NumArr( sortedMinIndex ) = curData  
  42.     
  43. ENDFOR
  44. * Print data from min to max
  45. "   从小到大排序:"
  46. FOR i = 1 TO NumCount
  47.     ?? ALLTRIM( STR( NumArr(i) ) ) + "  "
  48. ENDFOR
  49. * Print data from max to min
  50. "   从大到小排序:"
  51. FOR i = NumCount TO 1 STEP -1
  52.     ?? ALLTRIM( STR( NumArr(i) ) ) + "  "
  53. ENDFOR
  54. * Print from both ends to center
  55. "   两端大中间小:"
  56. FOR i = NumCount TO 1 STEP -2
  57.     IF i>0
  58.         ?? ALLTRIM( STR( NumArr(i) ) ) + "  "
  59.     ENDIF
  60. ENDFOR
  61. IF i=0
  62.     startIndex = 1
  63. ELSE
  64.     startIndex = 2
  65. ENDIF
  66. FOR i = startIndex  TO NumCount STEP 2
  67.     IF i <= NumCount
  68.         ?? ALLTRIM( STR( NumArr(i) ) ) + "  "
  69.     ENDIF
  70. ENDFOR

三、编程思路:

        首先,我们要用一个数组来接收用户输入的原始数据。根据用户指定的数据个数来定义数组维数,并逐个接收用户输入的数据保存到数组里。用户输入数据完毕,即可打印原始数列。
为了实现数据的从大到小、从小到大以及两头大中间小的排序,首先就要将该数组从小到大递增排序,然后实现另外两种排序就相对简单了。
        对原始序列进行排序的方法很多,有冒泡排序、选择排序、希尔排序及插入排序等,这里选择使用插入排序算法。
总体的思路是假设已经有一个已经排序过的序列,向该序列中插入一个新的数据,新数据放在这个已经排序的序列中适当的位置,保证插入新数据后的序列还是一个有序序列。
        对于一个长度为N的原始序列a [1],a[2],…a[N],我们可以认为第一个数据a[1]是有序的(即这个有序序列只包含一个数据a[1]),这时我们将原始序列中第2个数据a[2]插入这个只包含一个数据的有序序列中,并保证插入后的序列“a[1],a[2]”仍然是有序的。至此,原始序列可以分为已排序和未排序的两个部分,第1个及第2个数据“a[1],a[2]”是有序的,第3个至第N个数据“a[3],a[4],…a[N]”仍然是未排序的。这时我们继续将第3个数据a[3]插入到有序序列中(包含第1个数据和第2个数据的序列“a[1],a[2]”)并保证插入后第1至第3个数据“a[1],a[2],a[3]”是有序的。依此类推,直到第N个数据插入到由第1个至第N-1个数据组成的   有序序列“a[1],a[2],…a[N-1]”中,并保证插入后这个N个数据都是有序的。
        一般的,假设序列中第1个至第i( 1<=i<N )个数据“a[1],a[2],…a[i]”是已经排序的,我们将第i+1个数据插入到第1至i-1个数据组成的序列中,为了保证插入后的包含i+1个数据的序列仍然有序,就要将第i+1个数据a[i+1]放在有序序列中适当的位置。
由于序列“a[1],a[2],…a[i]”是已经排序的,我们可以将数据a[i+1]与已经排序的序列按递增或递减方向依次做对比,以找到a[i+1]在有序序列中应该处在的位置。例如,将数据a[i+1]依次与数据a[1]、a[2]、…a[i]做比较,如果a[i+1]比当前比较的数据a[j] ( 1<=j<=I )小,则应将a[i+1]放在a[j]的位置,否则继续与下一个数据比较。
由于序列“a[1],a[2],…a[N]”是已经排序的,所以插入a[i+1]时可以采用“折中查找”算法,而不必将a[i+1]与有序数列中的数据逐个比较,大大减小比较次数,降低复杂度。将设m=(1+i)/2,即a[m]是a[1]…a[i]数列的中间数据,我们可以直接将a[i+1]与a[m]进行比较,如果a[i+1]>a[m],则继续将a[i+1]与“a[m+1]…a[N]”的中间数据进行比较,反之则与“a[1]…a[m-1]”的中间数据进行比较。依次类推,直至最终找到a[i+1]的位置。
        在进行a[1]…a[N]的排序后,就可以按1..N的顺序打印出递增数列及按从N…1的序列打印出递减数列。
为了打印出两头大中间小的序列,分两步打印。第一步从N..1的顺序间隔打印,即打印a[N]、a[N-2]、a[N-4]… a[3]、a[1]。(如果N是偶数则打印a[N]、a[N-2]、a[N-4]… a[4]、a[2])。第二步从1…N的顺序间隔打印a[2]、a[4]…a[N-1](如果N是偶数则打印a[1]、a[3]、…a[N-1])。

 

四、 程序分析


1. 将用户输入的“数据个数”保存到变量NumCount,声明一个长度为NumCount的数组NumArr,依次接收用户输入的数据保存到数组NumArr里。
2. 用一个循环输出数组NumArr里的所有数据,即输出用户输入的原始数列。
3. 对数组NumArr进行递增排序。从第2个数据开始至最后一个数据循环插入到前面已经排序的数列中。
1) curIndex 为当前循环中待插入的数据,即到此循环时,第1个到curIndex-1个数据是已经排序的;sortedMinIndex和sortedMaxIndex为已经排序的序列的最小和最大的索引;
2) 用折中查找法在已经排序的数列中找到第curIndex个数据应该存放的位置(即最终sortedMinIndex所在的位置);
3) 将sortedMinIndex的到curIndex-1的数据依次后移;
4) 将curIndex所在位置的原来数据放到sortedMinIndex位置上,从而达到从1到curIndex的数据都是排序过的目的。
4.将已经排序的数组NumArr从1到NumCount的顺序输出,即输出从小到大的数列;
5.将已经排序的数足从NumCount到1 的顺序输出,即输出从大到小的数列;
6.输出两头大中间小的数列:
   1)从NumCount到1的顺序间隔输出数列,既循环变量i的步长为-2。
   2) 第一步输出完毕后,最后一个输出的数据只能是NumArr数组的第一个数据或第二个数据,即循环终止后i的值是-1或0。如果i是0,则第一步最后输出的是NumArr的第2个数据,本次输出应该从第1个数据开始;否则上次最后输出的是NumArr的第1个数据,本次循环应该从2个数据开始输出。且本次循环直到NumCount间隔输出。

【上篇】
【下篇】

抱歉!评论已关闭.