Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 气泡排序无限循环误差的变化_Python_While Loop_Bubble Sort - Fatal编程技术网

Python 气泡排序无限循环误差的变化

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循环永远不会终止。查看排序后的序列,它似乎会重复

在一个特定的棋盘游戏中,只有一行,它由N个空格组成,从左到右编号为0到N-1。也有N个弹珠,编号为0到N-1,最初按任意顺序排列。之后,有两个动作可供选择,一次只能完成一个动作:

  • 切换:在位置0和1切换弹珠
  • 旋转:移动 弹珠在位置0到位置N-1,并移动所有其他弹珠 左边一个空格(下一个索引)
目标是按顺序排列大理石,每个大理石i位于位置i

我编写的代码适用于发布在问题上的示例(1 3 0 2),但当我将额外的数字4随机添加到列表中时,while循环永远不会终止。查看排序后的序列,它似乎会重复地遍历多个相同的序列。我不知道为什么它会适用于一个系列,但不适用于下一个系列

另外,我似乎不知道如何将输出打印为用空格分隔的数字,而不是带括号和逗号的列表。问题要求我们将输出打印为用空格分隔的数字。在此方面的任何帮助都将不胜感激

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循环,但此代码现在更易于阅读。