Python 气泡排序无限循环误差的变化
在一个特定的棋盘游戏中,只有一行,它由N个空格组成,从左到右编号为0到N-1。也有N个弹珠,编号为0到N-1,最初按任意顺序排列。之后,有两个动作可供选择,一次只能完成一个动作:Python 气泡排序无限循环误差的变化,python,while-loop,bubble-sort,Python,While Loop,Bubble Sort,在一个特定的棋盘游戏中,只有一行,它由N个空格组成,从左到右编号为0到N-1。也有N个弹珠,编号为0到N-1,最初按任意顺序排列。之后,有两个动作可供选择,一次只能完成一个动作: 切换:在位置0和1切换弹珠 旋转:移动 弹珠在位置0到位置N-1,并移动所有其他弹珠 左边一个空格(下一个索引) 目标是按顺序排列大理石,每个大理石i位于位置i 我编写的代码适用于发布在问题上的示例(1 3 0 2),但当我将额外的数字4随机添加到列表中时,while循环永远不会终止。查看排序后的序列,它似乎会重复
- 切换:在位置0和1切换弹珠李>
- 旋转:移动 弹珠在位置0到位置N-1,并移动所有其他弹珠 左边一个空格(下一个索引)
class MarblesBoard:
"""creates a marble board with number marbles in specific spots"""
def __init__(self, marble_sequence):
self.board = [x for x in marble_sequence]
def __str__(self):
return str(self.board)
def __repr__(self):
return "%r " % (self.board)
def switch(self):
"""switch the marbles in position 0 and 1"""
self.board[0], self.board[1] = self.board[1], self.board[0]
return self.board
def rotate(self):
"""Move the marble in position 0 to position N - 1, and move all other marbles one space to the left (one index lower)"""
copy_board = self.board.copy()
copy_board[len(self.board)-1] = self.board[0]
for x in range(1, len(self.board)):
copy_board[x - 1] = self.board[x]
self.board = copy_board
return self.board
def is_sorted(self):
return self.board == sorted(self.board):
class Solver:
"""solves the marble sorting game when given a marble board as input"""
def __init__(self, MarblesBoard):
self.steps = 0
self.board = MarblesBoard.board
return
def solve(self):
n = len(self.board)
# print("n = ", n)
print(self.board)
while MarblesBoard.is_sorted(self) == False:
if self.board[0] > self.board[1]:
MarblesBoard.rotate(self)
print(self.board)
self.steps += 1
else:
MarblesBoard.switch(self)
print(self.board)
self.steps += 1
print("total steps: ", self.steps)
关于输出,这里的示例输出代码运行良好:
board2 = MarblesBoard((1,3,0,2))
solver = Solver(board2)
solver.solve()
[1, 3, 0, 2]
[3, 1, 0, 2]
[1, 0, 2, 3]
[0, 2, 3, 1]
[2, 0, 3, 1]
[0, 3, 1, 2]
[3, 0, 1, 2]
[0, 1, 2, 3]
total steps: 7
但是,如果我在起始板中添加4:
board2 = MarblesBoard((1,3,0,2,4))
solver = Solver(board2)
solver.solve()
[1, 3, 0, 2, 4]
[3, 1, 0, 2, 4]
[1, 0, 2, 4, 3]
[0, 2, 4, 3, 1]
[2, 0, 4, 3, 1]
[0, 4, 3, 1, 2]
[4, 0, 3, 1, 2]
[0, 3, 1, 2, 4]
[3, 0, 1, 2, 4]
[0, 1, 2, 4, 3]
[1, 0, 2, 4, 3]
[0, 2, 4, 3, 1]
[2, 0, 4, 3, 1]
[0, 4, 3, 1, 2]
[4, 0, 3, 1, 2]
[0, 3, 1, 2, 4]
[3, 0, 1, 2, 4]
请注意,3 0 1 2 4作为第二次迭代和最后列出的迭代重复。由于while循环的结构,由于发生了相同的序列,执行了相同的步骤,循环无限继续。那么,它到底是如何在冒泡排序上变化的呢?大多数排序都有一种方法将已排序和未排序的数据保存在不同的区域中,这样就可以清楚地知道已排序的内容。这类人似乎不这样做 看起来发生切换的唯一标准是当
board[0]>board[1]
时。真的就这些吗
我对守则的建议如下:
class MarblesBoard:
def __init__(self, marble_sequence):
self.board = [x for x in marble_sequence]
这不是有点多余吗?为什么不:
class MarblesBoard:
def __init__(self, marble_sequence):
self.board = marble_sequence
我似乎不知道如何把输出打印成数字
被一个空格隔开
这让我来看看您的\uuuu str\uuu
实现:
def __str__(self):
return str(self.board)
那不行。看看我在shell中尝试执行类似操作时得到的字符串:
>>> str([1, 2, 3])
'[1, 2, 3]'
>>>
您最好使用str.join
:
def __str__(self):
return " ".join(map(str, self.board))
您的开关
方法看起来不错,只是您不需要从中返回任何内容。只需交换元素,这就是你所需要做的
如果我正确理解了rotate
方法,它可以简化:
def rotate(self):
self.board.append(self.board.pop(0))
同样,您不需要从这个函数返回任何内容
您的已排序
也可以简化:
def is_sorted(self):
return self.board == sorted(self.board)
我也可能会在你的MarblesBoard
类中添加一个名为should\u rotate
的方法,该方法返回True
或False
,具体取决于解算器是否应该旋转或切换。它将在以后由解算器使用:
def should_rotate(self):
return self.board[0] > self.board[1]
接下来是解算器
类。首先是\uuuu init\uuu
方法:
通过命名参数MarblesBoard
,(与类的名称相同),可以隐藏类的标识符-因此我不会调用该参数。我认为marbles\u board
是一个更好的名字
第二,我看不出在\uuuu init\uuuu
中显式地将步骤
作为实例变量的好理由,因为您使用它的唯一地方是solve
方法。我现在就把它扔掉
第三,我认为将self.board
绑定到MarblesBoard
实例的board
对象不是一个好主意。如果您的解算器
类基本上只围绕大理石板.board
,那么您甚至可以不上这个类,只在大理石板
类中完成所有解算。同样,您不需要显式地从\uuuu init\uuu
返回
class Solver:
def __init__(self, marbles_board):
self.marbles_board = marbles_board
solve
也可以简化一点:
def solve(self):
number_of_steps = 0
while not self.marbles_board.is_sorted():
if self.marbles_board.should_rotate():
self.marbles_board.rotate()
else:
self.marbles_board.switch()
number_of_steps += 1
print(f"Number of steps: {number_of_steps}")
有趣的是,您的solve
实现工作得很好,看到您如何传入self
(Solver
对象)作为rotate
和switch
方法的参数。您的已排序
方法可以简单地返回self.board==sorted(self.board)
。很高兴当条件为True
@dumdum时,您没有返回False
——除非它完全回答了您的问题。我的理解是,传统的冒泡排序会查看索引[0]和[1],然后在移动到索引[1]和[2]之前对其进行排序,然后一直排序到索引[n-1]和[n]。然后它将重复此操作直到索引[n-2]和[n-1]等等。此版本仅切换索引[0]和[1]但是可以使用旋转函数向下移动列表。我会将其比作一个已更改的参考框架。不是将索引向下移动,而是移动列表。感谢您的帮助!添加4时仍然有一个无限的while循环,但此代码现在更易于阅读。