Бульбашка Сортувати домашнє завдання


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
По суті повідомлення: "У мене проблеми з кодуванням. Це те, що я зробив, воно не працює". Очевидно, є неявне "Чи може хтось дати мені вказівки, будь ласка?" На відміну від багатьох запитань щодо домашнього завдання, це (а) добре написано, (б) передує щодо домашнього завдання, та (в) включає гарну спробу вирішення проблеми. Я не думаю, що відсутність фактичного знака запитання занадто сильно
погіршує

36
Сортування бульбашок використовується як інструмент навчання, оскільки це найпростіший алгоритм сортування для розуміння більшості людей. Це хороша точка входу для вивчення сортування та алгоритмів загалом. Якби ми навчали лише тих речей, якими насправді користувалися б люди, обговорення сортування розпочалося б і закінчилося «використовувати порядок сортування бібліотеки».
Білл Ящірка

38
Це запитання - дитина-постер для того, як поставити хороші запитання "домашнього завдання". На думку Джона Фухі, є зразок коду, він добре написаний, і афіша дуже намагається зробити так, щоб нам було легко допомогти. Молодці, Джошун.
Джаррет Харді

20
Сортування бульбашок - це не простий алгоритм сортування, який люди можуть зрозуміти. Із власного досвіду, і з досвіду викладання я можу впевнено сказати, що сортування вставки, сортування вибору, сортування міні (мінімум сортування елементів), навіть (для деяких студентів) об'єднання і кварцкорт легше зрозуміти - адже вони дещо відповідають природні способи сортування списку, але сортування бульбашок просто штучне. Крім того, сортування бульбашок схильне до багатьох помилок один за одним і нескінченних помилок циклу, як це питання тут. Як каже Кнут, "схоже на те, що"
міхурний

Відповіді:


127

Щоб пояснити, чому ваш сценарій не працює зараз, я перейменую цю змінну unsortedв sorted.

Спочатку ваш список ще не відсортований. Звичайно, ми налаштувались sortedна False.

Як тільки ми починаємо whileцикл, ми припускаємо, що список вже відсортований. Ідея така: як тільки ми знайдемо два елементи, які не в потрібному порядку, ми 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для "індексу".

    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])є (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
Тільки на тому останньому біті коду міхур нічого не повертає, тому кінцевим результатом є те, що друкується "None". Ви, мабуть, або хочете повернути список, або зробити бульбашку (my_list), а потім надрукувати мій список.
Tung Nguyen

9
+1 добре структурована, чітка порада. Приємно бачити, як ви читаєте читача через те, що ви зробили і чому, а не просто написати швидкий виправлення.
Том Лейс

1
Я програміст на C #, тому це може бути просто тому, що я не отримую Python, але вам не потрібно щось в циклі, щоб відняти 1 від довжини, щоб отримати звичайний алгоритм сортування бульбашок?
Мартін Браун

20
Це наївна (але не неправильна) реалізація Bubble Sort. Після кожної ітерації whileциклу найбільший елемент "бульбашки" до кінця списку. Отже, після однієї ітерації останній елемент, безумовно, знаходиться в потрібному місці (і не переміщуватиметься послідовними ітераціями). Віднімаючи 1 від довжини, ви оптимізуєте алгоритм, лише сортуючи ще не відсортований length-nпідспис ( передні елементи списку). Я вирішив пропустити цю оптимізацію, оскільки це скоріше оптимізація, ніж життєва частина алгоритму.
Веслі

2
Put it all together, and you get this:... ну, ви пропустили це:The range command can also take just one argument (named stop).
Пітер Пергач

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
Це трохи погано, що для цієї відповіді не існує кнопки "WRONG". Я думаю, що це питання та відповіді - і особливо голосування - мають бути озвучені наступного разу, коли Джоел Спольський розповість про те, наскільки добре він налаштований на соціальну взаємодію на потоковому потоці.
Даніель Мартін

@Daniel: ти можеш робити те, що можуть зробити інші люди з достатньою репутацією (100) - спростуючи неправильну відповідь. Існує зародок істини - заперечуються умови, закладені у змінних прапора, погано. Хоча це не вся відповідь - я думаю, що @McWafflestix має рацію.
Джонатан Леффлер

2
Ви праві, хлопці, я передчасно відповів на це. Вибач за це.
Мартін Кот

2
@Martin - і я повинен зазначити, що я більше здивований / шокований голосуванням, ніж відповідь. Система репутації заохочує вас отримати цю першу відповідь відразу. Розбита частина - це те, як проголосується неправильна відповідь.
Даніель Мартін

2
Я підозрюю, що більшість людей голосують, не розуміючи в першу чергу питання (як і те, як я відповів на питання). ОТОГ, особа, яка задає запитання, має право вибору "правильної" відповіді після цього.
Мартін Кот

7

Використання змінної Unsorted неправильно; ви хочете мати змінну, яка повідомляє, чи ви поміняли два елементи; якщо ви це зробили, ви можете вийти зі свого циклу, інакше вам потрібно повторити цикл. Щоб виправити те, що у вас є, просто покладіть "несортований = помилковий" в тіло вашого, якщо випадок; видаліть ваш інший випадок; і поставте "unsorted = true" перед forциклом.


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
Мабуть, правда, mtasic ... але все, що позначено як домашнє завдання, є найбільш інструктивно налаштованим, а не переписаним (особливо, коли воно визначене як домашнє завдання в ОП).
Джаррет Харді

1
Це ідеальне переписування текстової книги «Міхур» на зразок більшості людей. Я написав те саме.
Лакшман Прасад

2
додавання гарної інформації корисно на мій погляд. так гарна відповідь .. подумав, що ти можеш використовувати прапор, щоб зламати якнайшвидше.
Grijesh Chauhan

3

# Дуже проста функція, можна оптимізувати (очевидно) за рахунок зменшення проблемного простору 2-го масиву. Але та ж О (п ^ 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]
Макото,

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

Чи не повинно бути "несортований = хибний" поза циклом for?
Svante

У неї було ще кілька проблем, ніж це;)
Тревор Оке

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

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 голосами
хтоpen

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 до а (в основному, всі несортовані елементи в цьому раунді) і порівнює його з суміжним елементом, і робить своп, якщо він більший за його сусідній елемент. В кінці раунду останній елемент сортується, і процес знову запускається без нього, доки всі елементи не будуть відсортовані.

Немає необхідності в умові 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циклу. В основному ви розглядаєте lastIndexз arrayі повільно 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 та Мартіном Котом, вирішили проблему нескінченного циклу, але мій код все ще не працює належним чином (для більшого списку він не буде сортуватися правильно). Я закінчився викиданням 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
знову ж таки, все, що вам дійсно потрібно зробити, - це використовувати булеву (назвати це недоторканою). оголосити це поза своїм циклом; цикл, поки недоторканий = вірно. в межах циклу while встановіть недоторканим істинність; в тілі вашого, якщо, встановіть недоторканим неправдиве. Роблячи це, ви можете викопати ваш інший випадок. таким чином, якщо ви коли-небудь переключите два елементи, ваш цикл продовжить; якщо цього не зробити, петля не буде.
Пол Соньє

-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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.