2017-02-18 6 views
0

Ive пытался написать быструю реализацию сортировки без использования нарезку, но я бегу в проблемы с полпути через время выполнения - было интересно, если кто-то может показать мне, где я буду неправильноPython сортировки слиянием без нарезки

I» ве добавил несколько заявлений печати (закомментированные), так что вы можете увидеть, что происходит до и после каждого этапа:

def mergesort(arr, l, r): 

    #print('start: ', arr[l:r]) 

    if len(arr[l:r]) <=1: 
     return arr[l:r] 

    mid = l + (r-l) // 2 
    left = mergesort(arr, l, mid) 
    right = mergesort(arr, mid, r) 

    l_idx = l 
    r_idx = mid 
    final = [] 

    while l_idx < mid and r_idx < r: 
     if arr[l_idx] <= arr[r_idx]: 
      final.append(arr[l_idx]) 
      l_idx+=1 
     else: 
      final.append(arr[r_idx]) 
      r_idx+=1 


    for val in arr[l_idx:mid]: 
     final.append(val) 

    for val in arr[r_idx:r]: 
     final.append(val) 

    #print('final: ', final[l:r]) 
    #print() 
    #print() 
    return final 



    print(merge([0, 9, 3, 7, 4, 2, 6, 1], 0, 8)) 

значения я получаю показывают, что для левой стороны была она работает хорошо, но для праву не делает. что любопытно, потому что, кажется, работает на правой стороне левого ...

стандартный вывод является:

start: [0, 9, 3, 7, 4, 2, 6, 1] 
start: [0, 9, 3, 7] 
start: [0, 9] 
start: [0] 
start: [9] 
final: [0, 9] 


start: [3, 7] 
start: [3] 
start: [7] 
final: [] 


final: [0, 3, 7, 9] 


start: [4, 2, 6, 1] 
start: [4, 2] 
start: [4] 
start: [2] 
final: [] 


start: [6, 1] 
start: [6] 
start: [1] 
final: [] 


final: [] 


final: [0, 4, 2, 6, 1, 9, 3, 7] 

ответ

0

Основная проблема заключается в том, что вы никогда не использовать left и right списки вы получите возврат из рекурсивных вызовов, но вам это нужно, поскольку arr не изменил ни одного бита этими вызовами. И когда вы исправляете это, вы также должны знать, что этот результирующий список начнется с индекса 0, независимо от значения l, которое вы передали через рекурсивные вызовы. Таким образом, это означает, что фактический цикл объединения должен начинаться с индекса 0, а не l.

Вот код, который вы должны иметь право после рекурсивных вызовов:

# concatenate the left and right results into arr 
arr = left + right 

# realign the indexes with the new arr 
mid -= l 
r -= l 
l_idx = 0 
r_idx = mid 

С этим изменением it will work.

NB: Вы сказали, что хотите сделать это без нарезки, но обратите внимание, что вы все еще нарезаете: всякий раз, когда вы используете нотацию , например arr[l:r], вы ломтик.

+0

Большое спасибо, не могли бы вы объяснить логику переустановки индексов, пожалуйста, спасибо 'mid = = и r - = l'. – vitamike

+0

Ну, 'l: r' - диапазон в' arr', над которым вы работаете, но возвращенные списки 'left' и' right' больше не отражают эту информацию. 'left + right' все еще имеет элементы' r-l', но они больше не начинаются с индекса 'l', а с индексом 0 (очевидно). Таким образом, все индексы, которые вы используете с этого момента, должны быть меньше, чем единицы. Это то, что '- = l': вычитает' l' из левого имени. – trincot

+0

Хорошо, еще раз спасибо :-) – vitamike

Смежные вопросы