【问题标题】:Bubble Sort Homework冒泡排序作业
【发布时间】:2010-10-28 01:53:20
【问题描述】:

在课堂上我们正在做排序算法,虽然我在谈论它们和编写伪代码时理解它们很好,但我在为它们编写实际代码时遇到了问题。

这是我在 Python 中的尝试:

mylist = [12, 5, 13, 8, 9, 65]

def bubble(badList):
    length = len(badList) - 1
    unsorted = True

    while unsorted:
        for element in range(0,length):
            unsorted = False
            if badList[element] > badList[element + 1]:
                hold = badList[element + 1]
                badList[element + 1] = badList[element]
                badList[element] = hold
                print badList
            else:
                unsorted = True

print bubble(mylist)

现在,这个(据我所知)排序正确,但一旦完成,它就会无限循环。

如何修复此代码,以便函数正确完成并正确排序任何(合理)大小的列表?

附:我知道我不应该在函数中真正打印,我应该有一个返回,但我还没有这样做,因为我的代码还没有真正工作。

【问题讨论】:

  • @KM - 他应该离开你的草坪吗?
  • 帖子本质上是:“我编码有问题,这是我做的,它不起作用。”显然有一个隐含的“有人可以给我一些指点吗?”与许多家庭作业问题不同,这个(a)写得很好,(b)是关于家庭作业的,(c)包括解决问题的良好尝试。我不认为缺少一个实际的问号会大大减损..
  • 冒泡排序被用作学习工具,因为它是大多数人最容易理解的排序算法。这是学习排序和一般算法的一个很好的切入点。如果我们只教人们实际使用的东西,那么关于排序的讨论就会以“使用库排序例程”开始和结束。
  • 这个问题是如何提出一个好的“家庭作业”问题的典型代表。就 John Fouhy 而言,有一个代码示例,它写得很好,而且发帖者正在努力让我们更容易提供帮助。干得好,joshhunt。
  • 冒泡排序不是一种易于理解的排序算法。从我自己的经验和教学经验来看,我可以自信地说,插入排序、选择排序、min-sort(最小元素排序),甚至(对于一些学生来说)mergesort和quicksort都更容易理解——毕竟它们有点对应排序列表的自然方式,但冒泡排序只是人为的。此外,冒泡排序容易出现许多错误和无限循环错误,就像这里的这个问题。正如 Knuth 所说,“冒泡排序似乎没有什么可推荐的,除了一个吸引人的名字……”

标签: python algorithm sorting bubble-sort


【解决方案1】:

为了解释为什么您的脚本现在无法运行,我将变量 unsorted 重命名为 sorted

起初,您的列表尚未排序。当然,我们将sorted 设置为False

一旦我们开始while 循环,我们就假设列表已经排序。这个想法是这样的:一旦我们发现两个元素的顺序不正确,我们将sorted 设置回Falsesorted 将保留为 True 只有在没有元素顺序错误的情况下

sorted = False  # We haven't started sorting yet

while not sorted:
    sorted = True  # Assume the list is now sorted
    for element in range(0, length):
        if badList[element] > badList[element + 1]:
            sorted = False  # We found two elements in the wrong order
            hold = badList[element + 1]
            badList[element + 1] = badList[element]
            badList[element] = hold
    # We went through the whole list. At this point, if there were no elements
    # in the wrong order, sorted is still True. Otherwise, it's false, and the
    # while loop executes again.

还有一些小问题可以帮助代码更高效或更易读。

  • for 循环中,您使用变量element。从技术上讲,element 不是一个元素;它是一个代表列表索引的数字。而且,还蛮长的。在这些情况下,只需使用临时变量名称,例如 i 用于“索引”。

    for i in range(0, length):
    
  • range 命令也可以只接受一个参数(名为stop)。在这种情况下,您将获得从 0 到该参数的所有整数的列表。

    for i in range(length):
    
  • Python Style Guide 建议使用下划线以小写字母命名变量。对于这样的小脚本,这是一个非常小的挑剔;更重要的是让您习惯 Python 代码最常见的样子。

    def bubble(bad_list):
    
  • 要交换两个变量的值,请将它们写为元组赋值。右侧被评估为一个元组(例如,(badList[i+1], badList[i])(3, 5)),然后分配给左侧的两个变量((badList[i], badList[i+1]))。

    bad_list[i], bad_list[i+1] = bad_list[i+1], bad_list[i]
    

把它们放在一起,你就得到了:

my_list = [12, 5, 13, 8, 9, 65]

def bubble(bad_list):
    length = len(bad_list) - 1
    sorted = False

    while not sorted:
        sorted = True
        for i in range(length):
            if bad_list[i] > bad_list[i+1]:
                sorted = False
                bad_list[i], bad_list[i+1] = bad_list[i+1], bad_list[i]

bubble(my_list)
print my_list

(顺便说一句,我也删除了你的打印声明。)

【讨论】:

  • 就在最后一段代码中,bubble 没有返回任何内容,因此最终结果是打印了“None”。您可能想要返回列表,或者执行 bubble(my_list) 然后打印 my_list。
  • +1 条理清晰的建议。很高兴看到您引导读者了解您所做的事情以及原因,而不仅仅是写一个快速修复。
  • 我是一名 C# 程序员,所以这可能只是因为我没有使用 Python,但你不需要在 while 循环中从长度中减去 1 来获得正常的冒泡排序算法?
  • 这是冒泡排序的一个幼稚(但并非不正确)的实现。在while 循环的每次迭代之后,最大的元素“冒泡”到列表的末尾。因此,在一次迭代之后,最后一个元素肯定在正确的位置(并且不会被连续迭代移动)。通过从长度中减去 1,您可以通过仅对尚未排序的子列表(列表的 length-n 最前面的元素)进行排序来优化算法。我选择跳过这个优化,因为它更像是一种优化而不是算法的重要部分。
  • Put it all together, and you get this: ...好吧,你错过了这个:The range command can also take just one argument (named stop).
【解决方案2】:

冒泡排序的目标是在每一轮中将较重的项移到底部,同时将较轻的项向上移动。在比较元素的内部循环中,您不必在每一轮中迭代整个列表最重的已经放在最后了。 swapped 变量是一个额外的检查,因此我们可以标记列表现在已排序并避免继续进行不必要的计算。

def bubble(badList):
    length = len(badList)
    for i in range(0,length):
        swapped = False
        for element in range(0, length-i-1):
            if badList[element] > badList[element + 1]:
                hold = badList[element + 1]
                badList[element + 1] = badList[element]
                badList[element] = hold
                swapped = True
        if not swapped: break

    return badList

您的版本 1,已更正:

def bubble(badList):
    length = len(badList) - 1
    unsorted = True
    while unsorted:
        unsorted = False
        for element in range(0,length):
            #unsorted = False
            if badList[element] > badList[element + 1]:
                 hold = badList[element + 1]
                 badList[element + 1] = badList[element]
                 badList[element] = hold
                 unsorted = True
                 #print badList
             #else:
                 #unsorted = True

     return badList

【讨论】:

    【解决方案3】:

    这就是当你使用负面含义的变量名时会发生的情况,你需要反转它们的值。以下内容会更容易理解:

    sorted = False
    while not sorted:
        ...
    

    另一方面,算法的逻辑有点偏离。您需要检查在 for 循环期间是否交换了两个元素。以下是我的写法:

    def bubble(values):
        length = len(values) - 1
        sorted = False
        while not sorted:
            sorted = True
            for element in range(0,length):
                if values[element] > values[element + 1]:
                     hold = values[element + 1]
                     values[element + 1] = values[element]
                     values[element] = hold
                     sorted = False
        return values
    

    【讨论】:

    • 这有点太糟糕了,我没有可以点击这个答案的“错误”按钮。我认为下次 Joel Spolsky 谈到他在 stackoverflow 上调整社交互动的效果如何时,需要重点介绍这个问题和回答——尤其是投票。
    • @Daniel:您可以做其他有足够声誉 (100) 的人可以做的事情 - 否决错误的答案。有一个真相 - 标志变量中包含的否定条件是不好的。不过,这不是完整的答案——我认为@McWafflestix 是对的。
    • 你们是对的,我过早地回答了这个问题。对此感到抱歉。
    • @Martin - 我应该指出,与答案相比,我对投票感到更惊讶/震惊。信誉系统鼓励您立即获得第一个答案。损坏的部分是如何对不正确的答案进行投票。
    • 我怀疑大多数人在投​​票时并没有真正理解这个问题(就像我回答问题的方式一样)。 OTOH,提出问题的人有权在事后选择“正确”答案。
    【解决方案4】:

    您对 Unsorted 变量的使用是错误的;你想要一个变量来告诉你是否交换了两个元素;如果你已经这样做了,你可以退出你的循环,否则,你需要再次循环。要解决您在这里遇到的问题,只需将“unsorted = false”放在 if 案例的正文中;删除您的 else 案例;并在 for 循环之前放置 "unsorted = true。

    【讨论】:

      【解决方案5】:
      def bubble_sort(l):
          for passes_left in range(len(l)-1, 0, -1):
              for index in range(passes_left):
                  if l[index] < l[index + 1]:
                     l[index], l[index + 1] = l[index + 1], l[index]
          return l
      

      【讨论】:

      • 我相信这个问题更像是“如何修复这段代码”,而不是“你的冒泡排序是什么?”
      • 你是绝对正确的,但以正确的方式做更重要
      • 没错,也许是 mtasic ......但是任何被标记为作业的东西都是最有指导意义的,而不是重写(尤其是当它被 OP 标记为作业时)。
      • 这是对大多数人学习的 C 冒泡排序教科书的完美重写。我也是这么写的。
      • 在我看来添加好的信息是有帮助的。这么好的答案..想你可能会使用标志尽早打破。
      【解决方案6】:

      #一个非常简单的函数,可以(显然)通过减少第二个数组的问题空间来优化。但相同的 O(n^2) 复杂度。

      def bubble(arr):
          l = len(arr)        
          for a in range(l):
              for b in range(l-1):
                  if (arr[a] < arr[b]):
                  arr[a], arr[b] = arr[b], arr[a]
          return arr 
      

      【讨论】:

      • 在 Python 中交换值的方式并不那么繁琐:arr[a], arr[b] = arr[b], arr[a]
      【解决方案7】:

      你有几个错误。第一个是长度,第二个是你对 unsorted 的使用(如 McWafflestix 所述)。如果要打印,您可能还想返回列表:

      mylist = [12, 5, 13, 8, 9, 65]
      
      def bubble(badList):
          length = len(badList) - 2
          unsorted = True
      
          while unsorted:
              for element in range(0,length):
                  unsorted = False
      
                  if badList[element] > badList[element + 1]:
                      hold = badList[element + 1]
                      badList[element + 1] = badList[element]
                      badList[element] = hold
                      print badList
                      unsorted = True
      
          return badList
      
      print bubble(mylist)
      

      eta:你说得对,上面的内容太糟糕了。我不通过更多示例进行测试,这很糟糕。

      def bubble2(badList):
          swapped = True
          length = len(badList) - 2
      
          while swapped:
              swapped = False
              for i in range(0, length):
                  if badList[i] > badList[i + 1]:
      
                      # swap
                      hold = badList[i + 1]
                      badList[i + 1] = badList[i]
                      badList[i] = hold
      
                      swapped = True
      
          return badList
      

      【讨论】:

      • “unsorted = False”不应该在for循环之外吗?
      • 它还有更多的问题 ;)
      【解决方案8】:

      我是一个新手,昨天开始阅读 Python。 受你的例子启发,我创造了一些可能更像 80 系风格​​的东西,但它仍然有点工作

      lista1 = [12, 5, 13, 8, 9, 65]
      
      i=0
      while i < len(lista1)-1:
          if lista1[i] > lista1[i+1]:
              x = lista1[i]
              lista1[i] = lista1[i+1]
              lista1[i+1] = x
              i=0
              continue
          else:
              i+=1
      
      print(lista1)
      

      【讨论】:

        【解决方案9】:

        原始算法的问题在于,如果列表中的数字较小,它不会将其带到正确的排序位置。程序每次都需要回到开头,以确保数字一直排序。

        我简化了代码,它现在适用于任何数字列表,无论列表如何,即使有重复的数字。这是代码

        mylist = [9, 8, 5, 4, 12, 1, 7, 5, 2]
        print mylist
        
        def bubble(badList):
            length = len(badList) - 1
            element = 0
            while element < length:
                if badList[element] > badList[element + 1]:
                    hold = badList[element + 1]
                    badList[element + 1] = badList[element]
                    badList[element] = hold
                    element = 0
                    print badList
                else:
                    element = element + 1
        
        print bubble(mylist)
        

        【讨论】:

          【解决方案10】:
          def bubble_sort(l):
              exchanged = True
              iteration = 0
              n = len(l)
          
              while(exchanged):
                  iteration += 1
                  exchanged = False
          
                  # Move the largest element to the end of the list
                  for i in range(n-1):
                      if l[i] > l[i+1]:
                          exchanged = True
                          l[i], l[i+1] = l[i+1], l[i]
                  n -= 1   # Largest element already towards the end
          
              print 'Iterations: %s' %(iteration)
              return l
          

          【讨论】:

          • 气泡较大的元素一直到最后。并减少结束计数器“n”,这样您就不必再次比较它。只要有交换,就继续 while 循环。最坏情况:O(N^2) 最好情况:O(N)
          【解决方案11】:
          def bubbleSort(alist):
          if len(alist) <= 1:
              return alist
          for i in range(0,len(alist)):
             print "i is :%d",i
             for j in range(0,i):
                print "j is:%d",j
                print "alist[i] is :%d, alist[j] is :%d"%(alist[i],alist[j])
                if alist[i] > alist[j]:
                   alist[i],alist[j] = alist[j],alist[i]
          return alist
          

          alist = [54,26,93,17,77,31,44,55,20,-23,-34,16,11,11,11]

          打印气泡排序(alist)

          【讨论】:

          • 请正确缩进您的代码示例:当然,这在 Python 中尤其重要。您可能还想解释为什么您的解决方案值得考虑考虑还有一个 100 票的答案
          【解决方案12】:
          def bubble_sort(a):
              t = 0
              sorted = False # sorted = False because we have not began to sort
              while not sorted:
              sorted = True # Assume sorted = True first, it will switch only there is any change
                  for key in range(1,len(a)):
                      if a[key-1] > a[key]:
                          sorted = False
                          t = a[key-1]; a[key-1] = a[key]; a[key] = t;
              print a
          

          【讨论】:

            【解决方案13】:

            一个更简单的例子:

            a = len(alist)-1
            while a > 0:
                for b in range(0,a):
                    #compare with the adjacent element
                    if alist[b]>=alist[b+1]:
                        #swap both elements
                        alist[b], alist[b+1] = alist[b+1], alist[b]
                a-=1
            

            这只是将元素从 0 带到 a(基本上是该轮中所有未排序的元素)并将其与相邻元素进行比较,如果大于其相邻元素则进行交换。在回合结束时,对最后一个元素进行排序,并且在没有它的情况下再次运行该过程,直到所有元素都已排序。

            sort 是否为真不需要条件。

            注意,这个算法只在交换时考虑数字的位置,所以重复的数字不会影响它。

            PS。我知道这个问题发布已经很久了,但我只是想分享这个想法。

            【讨论】:

              【解决方案14】:
              def bubble_sort(li):
                  l = len(li)
                  tmp = None
                  sorted_l = sorted(li)
                  while (li != sorted_l):
                      for ele in range(0,l-1):
                          if li[ele] > li[ele+1]:
                              tmp = li[ele+1]
                              li[ele+1] = li [ele]
                              li[ele] = tmp
                  return li
              

              【讨论】:

                【解决方案15】:
                def bubbleSort ( arr ):
                    swapped = True 
                    length = len ( arr )
                    j = 0
                
                    while swapped:
                        swapped = False
                        j += 1 
                        for i in range ( length  - j ):
                            if arr [ i ] > arr [ i + 1 ]:
                                # swap
                                tmp = arr [ i ]
                                arr [ i ] = arr [ i + 1]
                                arr [ i + 1 ] = tmp 
                
                                swapped = True
                
                if __name__ == '__main__':
                    # test list
                    a = [ 67, 45, 39, -1, -5, -44 ];
                
                    print ( a )
                    bubbleSort ( a )
                    print ( a )
                

                【讨论】:

                  【解决方案16】:
                  def bubblesort(array):
                      for i in range(len(array)-1):
                          for j in range(len(array)-1-i):
                              if array[j] > array[j+1]:
                                  array[j], array[j+1] = array[j+1], array[j]
                      return(array)
                  
                  print(bubblesort([3,1,6,2,5,4]))
                  

                  【讨论】:

                  • 虽然此代码可能会回答问题,但提供有关 如何 和/或 为什么 它解决问题的额外上下文将改善答案的长期性价值。
                  【解决方案17】:
                  arr = [5,4,3,1,6,8,10,9] # array not sorted
                  
                  for i in range(len(arr)):
                      for j in range(i, len(arr)):
                          if(arr[i] > arr[j]):
                              arr[i], arr[j] = arr[j], arr[i]
                  
                              print (arr)
                  

                  【讨论】:

                    【解决方案18】:

                    我考虑添加我的解决方案,因为这里的任何解决方案都有

                    1. 更大的时间
                    2. 更大的空间复杂度
                    3. 或操作过多

                    那么应该是

                    所以,这是我的解决方案:


                    def countInversions(arr):
                        count = 0
                        n = len(arr)
                        for i in range(n):
                            _count = count
                            for j in range(0, n - i - 1):
                                if arr[j] > arr[j + 1]:
                                    count += 1
                                    arr[j], arr[j + 1] = arr[j + 1], arr[j]
                            if _count == count:
                                break
                        return count
                    

                    【讨论】:

                      【解决方案19】:

                      如果有人对使用列表理解的更短的实现感兴趣:

                      def bubble_sort(lst: list) -> None:
                          [swap_items(lst, i, i+1) for left in range(len(lst)-1, 0, -1) for i in range(left) if lst[i] > lst[i+1]]
                      
                      
                      def swap_items(lst: list, pos1: int, pos2: int) -> None:
                          lst[pos1], lst[pos2] = lst[pos2], lst[pos1]
                      

                      【讨论】:

                        【解决方案20】:

                        这是不带for 循环的冒泡排序的不同变体。基本上,您正在考虑arraylastIndex,然后慢慢地decrementing 直到它成为数组的第一个索引。

                        algorithm 将继续像这样在数组中移动,直到完成整个传递而没有任何swaps 发生。

                        就性能而言,气泡基本上是Quadratic Time: O(n²)

                        class BubbleSort: 
                          def __init__(self, arr):
                            self.arr = arr;
                        
                          def bubbleSort(self):
                            count = 0;
                            lastIndex = len(self.arr) - 1;
                            
                            while(count < lastIndex):
                              if(self.arr[count] > self.arr[count + 1]):
                                self.swap(count)  
                              count = count + 1;
                        
                              if(count == lastIndex):
                                count = 0;
                                lastIndex = lastIndex - 1;   
                        
                          def swap(self, count):
                            temp = self.arr[count];
                            self.arr[count] = self.arr[count + 1];
                            self.arr[count + 1] = temp;
                            
                        arr = [9, 1, 5, 3, 8, 2]
                        p1 = BubbleSort(arr)
                        
                        print(p1.bubbleSort())
                        

                        【讨论】:

                          【解决方案21】:

                          the-fury 和 Martin Cote 提供的答案解决了无限循环的问题,但我的代码仍然无法正常工作(对于更大的列表,它无法正确排序。)。我最终放弃了 unsorted 变量并改用了计数器。

                          def bubble(badList):
                              length = len(badList) - 1
                              n = 0
                              while n < len(badList):
                                  for element in range(0,length):
                                      if badList[element] > badList[element + 1]:
                                          hold = badList[element + 1]
                                          badList[element + 1] = badList[element]
                                          badList[element] = hold
                                          n = 0
                                      else:
                                          n += 1
                              return badList
                          
                          if __name__ == '__main__':
                              mylist = [90, 10, 2, 76, 17, 66, 57, 23, 57, 99]
                              print bubble(mylist)
                          

                          如果有人能提供有关如何改进我在 cmets 中的代码的任何指示,将不胜感激。

                          【讨论】:

                          • 您可以通过跳过您知道已经排序的列表部分(因为之前的迭代)来加快冒泡排序。见en.wikipedia.org/wiki/Bubble_sort#Alternative_implementations
                          • 再一次,你真正需要做的就是使用一个布尔值(称它为 untouched)。在你的循环之外声明它;循环直到未触及 = true。在您的 while 循环中,将 untouched 设置为 true;在 if 的正文中,将 untouched 设置为 false。这样做,你可以放弃你的 else 案例。这样,如果您切换两个元素,您的循环将继续;如果你不这样做,循环不会。
                          【解决方案22】:

                          试试这个

                          a = int(input("Enter Limit"))
                          
                          
                          val = []
                          
                          for z in range(0,a):
                              b = int(input("Enter Number in List"))
                              val.append(b)
                          
                          
                          for y in range(0,len(val)):
                             for x in range(0,len(val)-1):
                                 if val[x]>val[x+1]:
                                     t = val[x]
                                     val[x] = val[x+1]
                                     val[x+1] = t
                          
                          print(val)
                          

                          【讨论】:

                            【解决方案23】:

                            如果这可能在 9 年后对您有所帮助... 它是一个简单的冒泡排序程序

                                l=[1,6,3,7,5,9,8,2,4,10]
                            
                                for i in range(1,len(l)):
                                    for j in range (i+1,len(l)):
                                        if l[i]>l[j]:
                                            l[i],l[j]=l[j],l[i]
                            

                            【讨论】:

                              【解决方案24】:
                              def merge_bubble(arr):
                                  k = len(arr)
                                  while k>2:
                                      for i in range(0,k-1):
                                          for j in range(0,k-1):
                                              if arr[j] > arr[j+1]:
                                                  arr[j],arr[j+1] = arr[j+1],arr[j]
                              
                                      return arr
                                      break
                                  else:
                                      if arr[0] > arr[1]:
                                          arr[0],arr[1] = arr[1],arr[0]
                                      return arr 
                              

                              【讨论】:

                                【解决方案25】:
                                def bubble_sort(l):
                                    for i in range(len(l) -1):
                                        for j in range(len(l)-i-1):
                                            if l[j] > l[j+1]:
                                                l[j],l[j+1] = l[j+1], l[j]
                                    return l
                                

                                【讨论】:

                                • 最好在你的代码中添加一些解释。
                                【解决方案26】:
                                def bubble_sorted(arr:list):
                                    while True:
                                        for i in range(0,len(arr)-1):
                                            count = 0
                                            if arr[i] > arr[i+1]:
                                                count += 1
                                                arr[i], arr[i+1] = arr[i+1], arr[i]
                                        if count == 0:
                                            break
                                    return arr
                                arr = [30,20,80,40,50,10,60,70,90]
                                print(bubble_sorted(arr))
                                #[20, 30, 40, 50, 10, 60, 70, 80, 90]
                                

                                【讨论】:

                                  【解决方案27】:

                                  def bubbleSort(a): def swap(x, y): temp = a[x] a[x] = a[y] a[y] = temp #outer loop for j in range(len(a)): #slicing to the center, inner loop, python style for i in range(j, len(a) - j):
                                  #find the min index and swap if a[i] < a[j]: swap(j, i) #find the max index and swap if a[i] > a[len(a) - j - 1]: swap(len(a) - j - 1, i) return a

                                  【讨论】:

                                    猜你喜欢
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2013-10-09
                                    • 2015-09-12
                                    • 1970-01-01
                                    • 2017-04-03
                                    相关资源
                                    最近更新 更多