关于“冒泡法”排序程序的逆向思考。 点击:227 | 回复:2



PLC酷客

    
  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-12 16:55:34
楼主

关于“冒泡法”排序程序的逆向思考。


在一些资料上看到,“冒泡法”排序一般是从最后一个数据开始,向地址小的方向相邻两个数据比较,并按照从小到大或者从大到小排序的一种算法。在数据比较、移动的过程中,数据的运动,看起来好像水中的气泡向上运动。故而称之为“冒泡法”排序。

“冒泡法”排序,在知道数据的起始地址、数据个数、数据类型后,需要算出最后一个数据的地址,并从最后的一个地址开始运算排序。我在想,为什么不能从数据的起始地址开始排序呢,如果采用这种“下沉法”排序,还能省去计算数据的结束地址,程序应该会更简洁。于是自己就试着写了一下“下沉法”排序的代码,并测试通过。

排序环境:224CPU,从VB1000开始连续20个整数,从小到大排序。“下沉法”排序算法参考代码如下:

//╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬给外循环体、内循环体的循环次数赋初值╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬
LD     SM0.0                              //开始执行从小到大的排序程序
MOVW   19, LW2                     //给外循环次数(数据个数-1)赋初值
MOVW   19, LW6                     //给内循环次数(数据个数-1)赋初值
//╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬建立外循环体并定义排序的其实地址╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬
FOR    LW0, +1, LW2                //FOR外循环体循执行LW2次
MOVD   &VB1000, AC1            //将V区的起始地址赋给AC1,定义排序的起始地址
//╬╬╬╬╬╬╬╬╬╬╬╬╬╬建立内循环体并开始进行相邻的两个数据比较、移动╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬
FOR    LW4, +1, LW6              //FOR内循环体循执行LW6次
MOVD   AC1, AC2                    //把当前AC1里面的地址存储到AC2里面
+D     +2, AC2                           //AC2当前地址+2,存入AC2
LDW<   *AC2, *AC1                //如果AC2指向的地址里面的内容小于AC1指向的地址里面的内容
MOVW   *AC1, LW8                //那么将当前两个地址里面的内容互换
MOVW   *AC2, LW10              //如果AC2指向的地址里面的内容不小于AC1指向的地址里面的内容
MOVW   LW8, *AC2                //那么当前两个地址里面的内容保持不变
MOVW   LW10, *AC1             //★如果把小于比较指令改成大于比较指令,那么数据就是从大到小排序
LD     SM0.0
+D     +2, AC1                          //AC1当前地址+2,存入AC1
NEXT                                        //跳转到FOR内循环,如果内循环执行结束,程序往下执行
//╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬内循环执行结束,进入外循环执行╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬
DECW   LW6                          //★内循环体执行结束,将内循环体的循环次数减1
NEXT                                       //跳转到FOR外循环,如果外循环执行结束,程序往下执行


上面代码基本采用临时变量作运算的,有兴趣的朋友,还可以将其封装成一个子程序,可以实现多次调用。



楼主最近还看过



PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-12 16:55:51
1楼

既然N侠想把这个排序程序封装成一个子程序,我建议进一步对循环体做一下优化。
基于这样的前提:排序是对word进行,因此一次就可把队列中的一对数取进来比较,需要交换时,再交叉存下去。
设AC1中存放指针,循环体如下:
LD     SM0.0
MOVD   *AC1, LD10                  // 取进一对相邻的数
LDW<   LW10, LW12                  // 大值冒上来,小值沉下去
MOVW   LW12, *AC1                  // 若上面条件成立,交叉存回
+I     2, AC1
MOVW   LW10, *AC1
NOT
+I     2, AC1                      // 若上面没有交换发生,地址+2

下面的写法是等效的,就是指针只在一个地方增加:
LD     SM0.0
MOVD   *AC1, LD10                  // 取进一对相邻的数
LDW<   LW10, LW12                  // 大值冒上来,小值沉下去
MOVW   LW12, *AC1                  // 若上面条件成立,交叉存回
LD     SM0.0
+I     2, AC1
ALD
MOVW   LW10, *AC1


通讯网-280395670

  • 精华:11帖
  • 求助:1帖
  • 帖子:432帖 | 10265回
  • 年度积分:0
  • 历史总积分:24711
  • 注册:2004年7月09日
发表于:2013-12-12 17:32:10
2楼

冒泡法不好,程序简单,但是运算时间长。。现在要求是程序文本长没有关系,关键是运行速度快。。存储器可以假定无限大。。


热门招聘
相关主题

官方公众号

智造工程师