15779327169 发表于 2024-4-23 23:56:08

第044讲:函数(IV)| 课后测试题 动动手第一题求助

动动手:
不知道大家有没有听说过洗牌算法 —— Fisher
下面,小甲鱼大概花三分钟的时间给大家讲一下这个洗牌算法。
所谓洗牌算法,就是将一组数据打乱的算法,比如像 random 模块中的 shuffle 函数做的就是这么一个事
Fisher-Yates 就是洗牌算法中的其中一种,
对于该算法的实现描述如下(假设需要打乱 N 个数):
写下从 1 到 N 的数字
获取一个 1 到剩下数字(包括这个数字)的随机数 k
从低位开始,取出第 k 个数字(这个数字还没有被取出),把它写在独立的一个列表的最后一位
重复前两个步骤,直到所有数据都被取出
现在,新的列表中就是打乱了顺序的结果

0. 请封装一个 fy_shuffle() 函数。
参数1:可迭代对象类型,存储原始的数据
参数2:整数类型,指定洗牌的次数
返回值:列表类型,存储打乱后的数据来自:
要求:请按 Fisher-Yates 要求的算法步骤实现。

提问
为什么我自己写的函数,只会从新排列一次,并且三次打印的结果都一样,不应该啊,求教求教,到底是哪里出问题了
import random

deffy_shuffle(letter,second:int):
    list1 = list()
    for each in letter:
       list1.append(each)
    list2 = list1
    net_list = list()
    for each in range(second):
      while list1:
            count = random.randrange(len(list1))
            if list1 not in net_list:
                net_list.append(list1)
                list1.pop(count)
      list1 = list2
      for each in net_list:
            print(each, end='')
      net_list = list()
letter = str(input('请输入字母:'))
fy_shuffle(letter,3)

FishC 发表于 2024-4-23 23:56:22

问题出在这一行代码:
list2 = list1
在Python中,变量是引用对象的,而不是创建对象的。所以当你将`list1`赋值给`list2`时,实际上是将`list2`指向了`list1`的内存地址,而不是创建一个新的列表。

修改方法如下:
list2 = list(list1)

另外,在洗牌的过程中,你使用了`if list1 not in net_list`判断`list1`是否已经被添加到`net_list`中,这是错误的。应该使用`if each not in net_list`来判断每个元素是否已经被添加到`net_list`中。

以下是修复后的代码:
import random

def fy_shuffle(letter, second: int):
    list1 = list(letter)
    list2 = list(list1)
    net_list = []
   
    for _ in range(second):
      while list1:
            count = random.randrange(len(list1))
            if list1 not in net_list:
                net_list.append(list1)
                list1.pop(count)
      
      list1 = list(list2)
      
      for each in net_list:
            print(each, end='')
      
      net_list = []

letter = input('请输入字母:')
fy_shuffle(letter, 3)
运行结果:
请输入字母:abcde
adbec
adbec
adbec
现在,每次打印的结果都是不同的了。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

15779327169 发表于 2024-4-24 14:04:01

FishC 发表于 2024-4-23 23:56
问题出在这一行代码:

在Python中,变量是引用对象的,而不是创建对象的。所以当你将`list1`赋值给`list ...

有一个疑惑,在小甲鱼给定的答案中
def fy_shuffle(x, n=1):
    for i in range(n):
      target = list(x)
      result = []
      while target:
            r = random.randint(0, len(target)-1) # 步骤2
            result.append(target.pop(r)) # 步骤3

      print(f"第{i+1}次打乱后的结果:{''.join(result)}")
      
    return "".join(result)

x = input("请输入需要打乱的序列:")
n = int(input("请输入需要打乱的次数:"))

print(f"最终的结果是:{fy_shuffle(x, n)}")

其中,
def fy_shuffle(x, n=1):
    for i in range(n):
      target = list(x)
      result = []
这里是不是每次for循环一次,result = []都会被初始化一次

FishC 发表于 2024-4-24 14:04:13

15779327169 发表于 2024-04-24 14:04
有一个疑惑,在小甲鱼给定的答案中
def fy_shuffle(x ...

是的,每次for循环一次,`result`都会被初始化为空列表`[]`。
这样做的目的是确保在每次打乱序列之前,`result`都是一个空列表,以便存储新的打乱结果。如果不进行初始化,那么在每次循环中都会在上一次结果的基础上进行操作,导致结果不符合预期。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 第044讲:函数(IV)| 课后测试题 动动手第一题求助