回 帖 发 新 帖 刷新版面

主题:Moz 的排列组合

----------------------------------------------------------------------
取消停止位置
改为无穷下一[size=4]排列[/size]:
顺序:从小到大循环

function nextpl$(a$)
l=len(a$)
for e=(l-1) to 1 step -1            
  if mid$(a$,e,1)<mid$(a$,e+1,1) then exit for
next
if e>0 then
  FOR i = l TO (e + 1) STEP -1        
    IF MID$(a$, i, 1) > MID$(a$, e, 1) THEN EXIT FOR
  NEXT
  b$ = MID$(a$, i, 1)               
  MID$(a$, i, 1) = MID$(a$, e, 1)
  MID$(a$, e, 1) = b$
end if
FOR i = (e + 1) TO (l + e + 1) \ 2  
    j = l + e + 1 - i
    b$ = MID$(a$, i, 1)
    MID$(a$, i, 1) = MID$(a$, j, 1)
    MID$(a$, j, 1) = b$
NEXT
nextpl$=a$
end function


-----------------------------------------------------------

[size=4]组合[/size]函数
顺序:由后至前循环。
可以很方便的和之前做的排列函数结合使用
只是存在一个缺点,就是不能有相同重复的字符
利用的字符串,当然,只要你有需要,
你可以很方便的延伸出去的。

function nextzh$(a$,b$)
for i=1 to len(b$)
  if instr(1,a$,mid$(b$,i,1))>i then
     mid$(b$,1,i)=mid$(a$,instr(1,a$,mid$(b$,i,1))-i,i)
     exit for
  endif
next
if i>len(b$) then b$=right$(a$,len(b$))
nextzh$=b$
end function

-----------------------------------------------------------------------------

[size=4]排列组合的联用[/size]
.......未完待续......

回复列表 (共19个回复)

沙发

[color=FF00FF]排列组合的联用[/color]
题目:列出从十个字母 abcdefghij 里取四个字母的所有组合排列。

(至于排列组合的个数我不记得怎么计算了,
所以我就不用 for 用 do 了,

x$="abcdefghij"
y$=right$(x$,4)
n$=y$
do                                  '------------> 组
  m$=n$                             '++++> 排      合
  do                                '++++> 列      变
    print m$,                       '++++> 的      化
    m$=nextpl$(m$)                  '++++> 套      的
  loop until m$=n$                  '++++> 子      外
  n$=nextzh$(x$,n$)                 '------------> 循
loop until n$=y$                    '------------> 环
system

function nextpl$(a$)
  l=len(a$)
  for e=(l-1) to 1 step -1            
      if mid$(a$,e,1)<mid$(a$,e+1,1) then exit for
  next
  if e>0 then
     FOR i = l TO (e + 1) STEP -1        
         IF MID$(a$, i, 1) > MID$(a$, e, 1) THEN EXIT FOR
     NEXT
     b$ = MID$(a$, i, 1)               
     MID$(a$, i, 1) = MID$(a$, e, 1)
     MID$(a$, e, 1) = b$
  end if
  FOR i = (e + 1) TO (l + e + 1) \ 2  
      j = l + e + 1 - i
      b$ = MID$(a$, i, 1)
      MID$(a$, i, 1) = MID$(a$, j, 1)
      MID$(a$, j, 1) = b$
  NEXT
  nextpl$=a$
end function

function nextzh$(a$,b$)
  for i=1 to len(b$)
      if instr(1,a$,mid$(b$,i,1))>i then
         mid$(b$,1,i)=mid$(a$,instr(1,a$,mid$(b$,i,1))-i,i)
         exit for
      endif
  next
  if i>len(b$) then b$=right$(a$,len(b$))
  nextzh$=b$
end function

优点在哪?
实现简单,不用数组,用变长字符串代替,灵活有序。
怎样实现?这些东西说是说得清楚,只是太长篇太哆嗦了,怕听者觉烦,
自己慢慢领会吧。

板凳

不错

3 楼

先简单的说说排列:
function nextpl$(a$)  
  l=len(a$)         '[color=FF00FF]得到字符串的长度[/color]
  for e=(l-1) to 1 step -1            '[color=FF00FF]找到不符合倒序的位置e[/color]
      if mid$(a$,e,1)<mid$(a$,e+1,1) then exit for
  next
  if e>0 then            '[color=FF00FF]如果存在不符合倒序的位置e的话[/color]
     FOR i = l TO (e + 1) STEP -1        '[color=FF00FF]在后面找比位置e的字符大的最小字符[/color]
         IF MID$(a$, i, 1) > MID$(a$, e, 1) THEN EXIT FOR
     NEXT
     b$ = MID$(a$, i, 1)     '[color=FF00FF]交换这两个位置的字符[/color]
     MID$(a$, i, 1) = MID$(a$, e, 1)
     MID$(a$, e, 1) = b$
  end if          '[color=FF00FF]如果全部符合倒序的话,就全部变成顺序(得最小值)[/color]
  FOR i = (e + 1) TO (l + e + 1) \ 2  '[color=FF00FF]把后面的倒序变成顺序排列(最小值)[/color]
      j = l + e + 1 - i
      b$ = MID$(a$, i, 1)
      MID$(a$, i, 1) = MID$(a$, j, 1)
      MID$(a$, j, 1) = b$
  NEXT
  nextpl$=a$
end function

举例:
1234     (全部顺序,这是最小值)
         (34不符合倒序,换一换位置成43得)
1243     (43符合倒序,24不符合倒序
           从43里取比2大的最小值3,和2调换位置成342
           再把后面的42按顺序排列成1324)
1324     (24不符合倒序,换一换位置成42得
1342     (34不符合倒序,在后面的42里找比3大的最小值4,
           和3换位置后,再把后面的32按顺序排列得
1423     (对换最后两位
1432     (14不符合倒序,在后面的432里找比1大的最小值2,
           换位置后把后面的431排顺序
2134      ......
..........不断的从后面往前去检查相邻两位字符的顺序,
              1. 逆序  (前一位比后一位字符大,跳过)
              2. 非逆序(前一位字符比后一位大)
                   A.从后面的字符串里找到比这位字符大的最小字符
                   B.对换位置
                   C.把后面的字符串按顺序排列

4 楼

这里谢谢MOZ了.收到这么好的教程..

真心感谢!!

5 楼

这个程序前面 还用数字标号的.我就不写了.

dim a(100)
j=1
n=9
for b=1 to n
  a(b)=b
next b
while j
for i=1 to n
print a(i);""l;
next i
gosub 500
gosub 1000
wend
end

500
j=n-1
while a(j)>a(j+1) and j>0
j=j-1
wend
return

1000
k=j+1
min =a(j+1)
for i=j+1 to n
if a(i)>a(j) and a(i)<min then
min=a(i)
k=2
next i
swap a(j),a(k)

for q=j+1 to n
for s=0 to n
if  a(s)>a(q) then
swap a(q),a(s)
next s
next q
return

6 楼

我先修改一下再来看

  n=9
  dim a(n)
  for b=1 to n
      a(b)=b
  next b

  j=1

while j

  print
  for i=1 to n
      print a(i);
  next i

  j=n-1
  while a(j)>a(j+1) and j>0
        j=j-1
  wend
  
  k=j+1
  min =a(k)
  for i=k to n
      if a(i)>a(j) and a(i)<min then
         min=a(i)
         k=i
      endif
  next i
  swap a(j),a(k)

  for q=j+1 to n
      for s=q+1 to n
          if a(s)<a(q) then swap a(q),a(s)
      next s
  next q

wend
end

我把结构改了,没改原来的流程,
我又改了好多小地方,可能是你这中间一手搞错的,
现在看明白了,和我的做法是一样的,
先检查倒序,非倒序则交换,然后后面排顺序。
只是我没用数组而用了字符串,省了数组这一段,
而且我还省略了一些既存的事实。
所以不能说他的比我的简单。
我的程序显得臃肿的地方是字符串中单个字符不能直接用swap交换。

7 楼

n=9                     '[color=FF00FF]9个元素[/color]
  dim a(n)                '[color=FF00FF]定义数组[/color]
  for b=1 to n            '[color=FF00FF]对数组赋值[/color]
      a(b)=b
  next b
  j=1                     '[color=FF00FF]设定循环条件,[/color]
while j    '[color=FF00FF]其实可以用 do...loop while j 代替的[/color]
  print    '[color=FF00FF]显示每一个排列[/color]
  for i=1 to n
      print a(i);
  next i

  j=n-1    '[color=FF00FF]从倒数第二个位置起检查[/color]
  while a(j)>a(j+1) and j>0  '[color=FF00FF]和它之后的一个相邻值比较[/color]
        j=j-1                '[color=FF00FF]如果符合倒序则继续向前比较[/color]
  wend                       '[color=FF00FF]不符合倒序就跳出[/color]
  k=j+1                      '[color=FF00FF]从j位置分段,k是后段首位置[/color]
  min =a(k)                  '[color=FF00FF]记录上一位置值[/color]
  for i=k to n               '[color=FF00FF]在后段找比j大的[/color]
      if a(i)>a(j) and a(i)<min then  '[color=FF00FF]最小值[/color]
         min=a(i)            '[color=FF00FF]因为没有利用前面已经[/color]
         k=i                 '[color=FF00FF]检查过的倒序进行循环[/color]
      endif                  '[color=FF00FF]也没有用exit for,有点费时[/color]
  next i
  swap a(j),a(k)             '[color=FF00FF]交换这两个位置上的值[/color]
  for q=j+1 to n             '[color=FF00FF]下面这个双重循环是对后段[/color]
      for s=q+1 to n         '[color=FF00FF]按顺序排序(从小到大)[/color]
          if a(s)<a(q) then swap a(q),a(s)  '[color=FF00FF]相当于冒泡法[/color]
      next s
  next q
wend

8 楼

很久没来过了  差点错过这样好的帖 辛苦啦!!!! MOZ 我崇拜你 [em1][em1][em1][em1]

9 楼

MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ

10 楼

正在惦记着很久没看见这个比我更神经的人呢
昨天还说起呢

我来回复

您尚未登录,请登录后再回复。点此登录或注册