泡泡排序作业


130

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

这是我在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)

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

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

PS:我知道我不应该在函数中真正打印输出,而应该得到返回值,但是我还没有这样做,因为我的代码还没有真正起作用。


29
@KM-他应该得到你的草坪吗?
艾登·贝尔

123
该帖子本质上是:“我在编码时遇到了麻烦,这是我所做的,它不起作用。” 显然有一个隐含的“有人可以给我一些指示吗?” 与许多家庭作业问题不同,(a)这个问题写得很好,(b)关于要做家庭作业是先行的,(c)为解决问题做了很好的尝试。我不认为缺乏实际的问号减损的太大..
约翰·福希

36
气泡排序被用作学习工具,因为它是大多数人最容易理解的排序算法。一般来说,这是学习排序和算法的一个很好的切入点。如果我们仅讲授人们实际使用的东西,则有关排序的讨论将以“使用库排序例程”开始和结束。
比尔蜥蜴

38
这个问题是如何提出一个好的“作业”问题的后代。就约翰·福伊(John Fouhy)而言,有一个代码示例,它写得很好,并且发布者正在努力使我们容易获得帮助。干得好,乔什亨特。
Jarret Hardie,2009年

20
冒泡排序并不是人们容易理解的简单排序算法。从我自己的经验和经验教学中,我可以自信地说,插入排序,选择排序,最小排序(最小元素排序),甚至(对于某些学生而言)合并排序和快速排序都更容易理解-毕竟,它们在某种程度上对应列表排序的自然方法,但冒泡排序只是人为的。此外,冒泡排序很容易出现许多一次性错误和无限循环错误,就像这里的问题一样。正如克努斯(Knuth)所说,“泡沫种类似乎没有什么值得推荐的,除了一个易记的名字……”
ShreevatsaR

Answers:


127

为了解释为什么您的脚本现在无法正常工作,我将变量重命名unsortedsorted

首先,您的列表尚未排序。当然,我们设置sortedFalse

一旦开始while循环,我们就假定该列表已经排序。想法是这样的:一旦找到两个顺序不正确的元素,便将其设置sortedFalse只有在没有顺序错误的元素时sorted才会保留。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“ index”。

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

    for i in range(length):
  • Python样式指南》建议使用下划线将变量命名为小写。对于这样的小脚本,这是一个很小的缺点。它会让您习惯于Python代码最常类似于的东西。

    def bubble(bad_list):
  • 要交换两个变量的值,请将它们写为元组分配。右侧被评估为元组(例如(badList[i+1], badList[i])is (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

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


1
仅在最后一段代码上,bubble不会返回任何内容,因此最终结果是打印了“ None”。您可能想要返回列表,或者执行bubble(my_list)然后打印my_list。
东阮

9
+1结构合理,清晰的建议。很高兴看到您引导读者了解您所做的事情和原因,而不仅仅是写一个快速修复程序。
汤姆·莱斯

1
我是C#程序员,所以这可能仅仅是因为我没有Python,但是您是否不需要在while循环中从长度中减去1来获得常规的冒泡排序算法?
马丁·布朗2009年

20
这是冒泡排序的幼稚(但不是不正确)实现。循环的每次迭代之后while,最大的元素“冒泡”到列表的末尾。这样,在一次迭代之后,最后一个元素肯定在正确的位置(并且不会因连续的迭代而移动)。通过从长度中减去1,可以通过仅对尚未排序的子列表(length-n列表的最前面的元素)进行排序来优化算法。我选择跳过此优化,因为它比算法的重要部分更重要。
韦斯利2009年

2
Put it all together, and you get this:...嗯,您错过了这个:The range command can also take just one argument (named stop).
PeterPerháč09年

10

气泡分类的目的是在每轮底部移动较重的项目,同时向上移动较轻的项目。在内部循环中,您可以比较元素,而不必每次都迭代整个列表。将最重的已经排在最后。该交换变量是一个额外的检查,所以我们可以标记列表现在可以正确排序,并避免不必要的计算仍在继续。

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

8

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

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

1
有点糟糕,我没有可以点击“错误”按钮的答案。我认为,下一次Joel Spolsky谈论他如何优化stackoverflow上的社交互动时,需要特别关注这个问题和答案,尤其是投票。
丹尼尔·马丁

@Daniel:您可以做其他信誉良好(100)的人可以做的事情-否决错误的答案。有一个事实的根源-标志变量中包含的否定条件是不好的。不过,这还不是全部答案-我认为@McWafflestix正确。
乔纳森·勒夫勒

2
你们是对的,我对此早回答了。对于那个很抱歉。
马丁·科特

2
@Martin-我应该指出,我对投票比对答案感到惊讶/震惊。信誉系统鼓励您立即获得第一个答案。残缺的部分是如何对不正确的答案进行投票。
丹尼尔·马丁

2
我怀疑大多数人最初投票时并没有真正理解问题(就像我回答问题的方式一样)。OTOH,提出问题的人有权在事后选择“正确的”答案。
马丁·科特

7

您对Unsorted变量的使用是错误的;您想要一个变量来告诉您是否交换了两个元素;如果这样做,则可以退出循环,否则,需要再次循环。要解决您在此处遇到的问题,只需在if情况的正文中输入“ unsorted = false”;删除其他情况;并在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

1
我相信问题更多地在于“如何解决此代码”,而不是“您的气泡排序是什么?”
乔什·亨特

4
您是绝对正确的,但是以正确的方式进行操作更为重要
mtasic85

6
没错,也许是错综复杂的……但是标记为家庭作业的任何东西都最有启发性地进行了调整,而不是重新编写(尤其是当OP标记为家庭作业时)。
Jarret Hardie

1
这是大多数人学习的课本C泡沫排序的完美重写。我写了一样。
Lakshman Prasad

2
在我看来,添加良好的信息会有所帮助。这么好的答案..以为您可能会使用标志尽早破解。
Grijesh Chauhan 2013年

3

#一个非常简单的函数,可以通过减少第二个数组的问题空间来优化(显然)。但是相同的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]
Makoto

1

您那里有几个错误。第一个是长度,第二个是您未排序的使用(如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)

埃塔:你是对的,上面的小车就像地狱一样。我的缺点是不通过更多示例进行测试。

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循环之外吗?
斯万特

它有更多的问题;)
Trevor Oke,2009年

1

我是一个新鲜的初学者,昨天开始阅读有关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)

1

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

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

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)

1
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

1
将较大的元素一直泡到最后。然后递减结束计数器“ n”,这样您就不必再次比较它了。只要有交换,就继续执行while循环。最坏的情况:O(N ^ 2)最好的情况:O(N)
Zile Rehman 2014年

1
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]

打印bubbleSort(alist)


请正确缩进您的代码示例:当然,这在Python中尤其重要。您可能还想解释为什么您的解决方案值得考虑,因为还有一个100票的答案
kdopen

1
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

1

一个简单的例子:

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。我知道这个问题发布已经很长时间了,但是我只想分享这个想法。


1
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)

0
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

0
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 )

0
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]))

1
尽管此代码可以回答问题,但提供有关如何和/或为什么解决问题的其他上下文将提高答案的长期价值。
亚历山大

0

我考虑添加我的解决方案,因为这里曾经有解决方案

  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

0

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

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]

0

这是不带for循环的气泡排序的另一种形式。基本上,您正在考虑的lastIndexarray然后慢慢进行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())

-1

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)

如果有人可以在注释中提供任何有关如何改进我的代码的指针,将不胜感激。


您可以跳过列表中您已经知道已排序的部分(由于先前的迭代),从而加快气泡排序的速度。请参见en.wikipedia.org/wiki/Bubble_sort#Alternative_implementations
Blorgbeard将于2009年

3
再次,您真正需要做的就是使用一个布尔值(称其为原值)。在循环外声明它;循环直到未触及= true。在while循环中,将untouched设置为true;在if的正文中,将untouched设置为false。这样做,您可以放弃其他情况。这样,如果您切换了两个元素,循环将继续;如果不这样做,循环将不会。
保罗·索尼尔

-1

试试这个

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)

-1

idk如果这可能会在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]

-1
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 


-1
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]

-3

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.