0

I'm very new in programming and Python, so please excuse in advance my lack of knowledge.

I’m trying to implement a recursive merge sort method in a class. However, when I try to run the program I get the following error:

RecursionError: maximum recursion depth exceeded while calling a Python object

This is because of left = self.merge(lst[:middle]) and right = self.merge(lst[middle:]).

Does someone know how this problem could be solved?

def merge(self, lst, reverse=False):

    middle = len(lst) // 2
    left = self.merge(lst[:middle])
    right = self.merge(lst[middle:])

    result = []
    i, j = 0, 0

    if not len(left) or not len(right):
        return left or right

    while i < len(left) and j < len(right):
        if reverse:
            if left[i] > right[j]:
                result.append(left[i])
                i += 1
            else:
                result.append(right[j])
                j += 1
        else:
            if left[i] < right[j]:
                result.append(left[i])
                i += 1
            else:
                result.append(right[j])
                j += 1

        if i == len(left) or j == len(right):
            result.extend(left[i:] or right[j:])
            break

    return result    


def _merge_sort(self, reverse=False):

    lst = list(self.unsorted_tuple)

    if len(lst) < 2:
        return lst

    return self.merge(lst)
Amit Yadav
  • 4,422
  • 5
  • 34
  • 79
Vicgen
  • 1
  • 3

1 Answers1

0

The problem is that you don't have a properly defined base case. In case of merge sort this would be checking if the passed list is either empty or has only one element (it is trivially true that it is sorted).

I'm guessing you're trying to do this with if not len(left) or not len(right). There's two problems with that. First, I don't think this code does what you think it does, play with it a bit in isolation to see how it behaves. See how I changed it and try to improve it.

Second, the test for the base case must be checked before calling the function again recursively. You never even come to this part because first thing that your merge function does is to call itself again! Here's a standalone merge function (not defined as a class method, I leave this to you):

def merge(lst, reverse=False):

    if len(lst) <= 1: 
        return lst

    middle = len(lst) // 2
    left = merge(lst[:middle])
    right = merge(lst[middle:])

    result = []
    i, j = 0, 0



    while i < len(left) and j < len(right):
        if reverse:
            if left[i] > right[j]:
                result.append(left[i])
                i += 1
            else:
                result.append(right[j])
                j += 1
        else:
            if left[i] < right[j]:
                result.append(left[i])
                i += 1
            else:
                result.append(right[j])
                j += 1

    if i == len(left):
                result.extend(right[j:])
    if j == len(right):
            result.extend(left[i:])

    return result    

I strongly recommend you Aditya Bhargava's Grokking Algorithms - it uses Python and is a good introductory book.

gstukelj
  • 2,291
  • 1
  • 7
  • 20