バブルソートの宿題


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)問題を解決するための良い試みが含まれている。私は..実際の疑問符の欠如があまりにも大幅に損なうとは思わない
ジョンFouhy

36
バブルソートは、ほとんどの人にとって理解しやすい最も簡単なソートアルゴリズムであるため、学習ツールとして使用されます。これは、一般的な並べ替えとアルゴリズムについて学ぶための良いエントリポイントです。人々が実際に使用するものだけを教えた場合、ソートの説明は「ライブラリソートルーチンの使用」で始まり、終わります。
トカゲに請求する

38
この質問は、良い「宿題」の質問をする方法のポスターの子です。John Fouhyの要点として、コードサンプルがあり、それはよく書かれていて、ポスターは私たちが手助けできるように一生懸命努力しています。よくやった、ジョシュン。
ジャレットハーディー

20
バブルソートは、人々にとって理解しやすいソートアルゴリズムではありません。私自身の経験と経験から、挿入ソート、選択ソート、最小ソート(最小要素ソート)、さらには(一部の学生にとって)マージソートとクイックソートは理解しやすいと自信を持って言えるでしょう。結局のところ、これらはある程度対応していますリストをソートする自然な方法ですが、バブルソートは人工的なものです。さらに、バブルソートは、この質問のように、多くのオフバイワンエラーと無限ループエラーの傾向があります。Knuthが言うように、「バブルソートは、キャッチーな名前を除いて、それを推奨するものは何もないようです...」
ShreevatsaR

回答:


127

スクリプトは今働いていない理由を説明するために、私は、変数の名前を変更しますunsortedsorted

最初は、リストはまだソートされていません。もちろん、に設定sortedFalseます。

whileループを開始するとすぐに、リストが既にソートされていると想定します。アイデアは次のとおりです。正しい順序になっていない2つの要素が見つかるとすぐに、にsorted戻しFalseます。間違った順序で要素がなかった場合にのみ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):
  • 2つの変数の値を交換するには、それらをタプル割り当てとして記述します。右側はタプルとして評価され(たとえば(badList[i+1], badList[i])is (3, 5))、次に左側の2つの変数に割り当てられます((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を出力します。
Tung Nguyen、

9
+1よく構成された明確なアドバイス。簡単な修正を書くだけでなく、読者が何をしたのか、またその理由を読者に説明できるのは素晴らしいことです。
トム・レイズ

1
私はC#プログラマーなので、Pythonを取得できないためと思われるかもしれませんが、whileループで長さから1を減算して通常のバブルソートアルゴリズムを取得する必要がありますか?
マーティンブラウン

20
これは、バブルソートの素朴な(ただし正しくない)実装です。whileループが繰り返されるたびに、最大の要素がリストの最後まで「泡立ち」ます。そのため、1回の反復後、最後の要素は間違いなく正しい場所にあります(連続する反復によって移動されることはありません)。長さから1を引くことにより、まだソートされていないサブリスト(リストのlength-n最前面の要素)のみをソートすることにより、アルゴリズムを最適化しています。この最適化はアルゴリズムの重要な部分よりも最適化であるため、この最適化をスキップすることを選択しました。
ウェズリー

2
Put it all together, and you get this:...まあ、これを見逃した:The range command can also take just one argument (named stop).
PeterPerháč2009年

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ループ中に2つの要素が交換されたかどうかを確認する必要があります。ここに私がそれを書く方法があります:

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がスタックオーバーフローでのソーシャルインタラクションをいかにうまく調整したかについて話すときに取り上げる必要があると思います。
ダニエルマーティン

@Daniel:十分な評判(100)を持つ他の人々ができることを行うことができます-間違った答えに反対票を投じてください。真実の胚芽があります-フラグ変数に安置されている否定された条件は悪いです。でも、それだけでは答えは出ません-@McWafflestixは正しいと思います。
ジョナサンレフラー

2
君たちは正しい、私はこれについて時期尚早に答えた。申し訳ありません。
Martin Cote、

2
@Martin-そして、私は答えよりも投票に驚いたりショックを受けたりしたことを指摘しておきます。評判システムは、最初の答えをすぐに得ることを奨励します。壊れた部分は、不正解の投票方法です。
ダニエルマーティン

2
(私が質問に答えたのと同じように)ほとんどの人はそもそも質問を本当に理解せずに投票していると思います。質問をする人、OTOHは後で「正しい」答えを選ぶ特権を持っています。
Martin Cote、

7

Unsorted変数の使用は間違っています。2つの要素を交換したかどうかを通知する変数が必要です。それを行った場合は、ループを終了できます。それ以外の場合は、再度ループする必要があります。ここにあるものを修正するには、ifケースの本文に「unsorted = false」を挿入するだけです。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

1
問題は、「バブルのソートは何ですか?」ではなく、「このコードを修正するにはどうすればよいですか?」
Josh Hunt、

4
あなたは絶対に正しいですが、正しい方法でそれを行うことがより重要です
mtasic85 '21

6
確かに、おそらくmtasic ...ですが、宿題としてタグ付けされたものはすべて、書き直されるのではなく、指示に従って調整されます(特に、OPによって宿題としてタグ付けされている場合)。
ジャレットハーディー

1
これは、ほとんどの人が研究している教科書Cのバブルソートを完全に書き直したものです。同じことを書いた。
ラクシュマンプラサード

2
良い情報を追加することは、私の見解では役立ちます。とても良い答えです。できるだけ早くフラグを使って破ることができると思います。
Grijesh Chauhan 2013

3

#非常に単純な関数で、2番目の配列の問題スペースを減らすことで(明らかに)最適化できます。しかし、同じ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で値を交換できるような方法でbelabored少しです: arr[a], arr[b] = arr[b], arr[a]

1

そこにはいくつかのエラーがあります。1つ目は長さで、2つ目は(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ループの外にあってはいけませんか?
Svante、

それよりもいくつかの問題がありました;)
Trevor Oke

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]

ふきだしソート


コードサンプルを正しくインデントしてください。これはもちろん、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は

3
繰り返しますが、本当に必要なのはブール値を使用することだけです(そのままにする)。ループの外で宣言してください。untouched = trueになるまでループします。whileループ内で、untouchedをtrueに設定します。ifの本文では、そのままにしてfalseに設定します。これを行うと、elseケースを破棄できます。このようにして、2つの要素を切り替えると、ループが継続します。そうしないと、ループは行われません。
ポール・ソニア

-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

これが9年後にあなたを助けるかもしれないならidk ...それは単純なバブルソートプログラムです

    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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.