主题:Moz 的排列组合
moz
[专家分:37620] 发布于 2005-12-11 10:15:00
----------------------------------------------------------------------
取消停止位置
改为无穷下一[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个回复)
沙发
moz [专家分:37620] 发布于 2005-12-11 10:57:00
[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
优点在哪?
实现简单,不用数组,用变长字符串代替,灵活有序。
怎样实现?这些东西说是说得清楚,只是太长篇太哆嗦了,怕听者觉烦,
自己慢慢领会吧。
板凳
superlcr [专家分:2300] 发布于 2005-12-11 12:24:00
不错
3 楼
moz [专家分:37620] 发布于 2005-12-19 13:47:00
先简单的说说排列:
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 楼
net56789 [专家分:210] 发布于 2005-12-20 20:47:00
这里谢谢MOZ了.收到这么好的教程..
真心感谢!!
5 楼
net56789 [专家分:210] 发布于 2005-12-22 12:39:00
这个程序前面 还用数字标号的.我就不写了.
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 楼
moz [专家分:37620] 发布于 2005-12-22 14:18:00
我先修改一下再来看
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 楼
moz [专家分:37620] 发布于 2005-12-23 13:17:00
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 楼
困难 [专家分:50] 发布于 2006-01-07 22:50:00
很久没来过了 差点错过这样好的帖 辛苦啦!!!! MOZ 我崇拜你 [em1][em1][em1][em1]
9 楼
def [专家分:3380] 发布于 2006-01-14 17:35:00
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
10 楼
moz [专家分:37620] 发布于 2006-01-14 18:28:00
正在惦记着很久没看见这个比我更神经的人呢
昨天还说起呢
我来回复