Home > Mobile >  Merge Sort not working with an array bigger than 10^7 elements
Merge Sort not working with an array bigger than 10^7 elements

Time:03-15

My algorithm works perfectly for an array of up to 10^6 elements, even though it is not that efficient it does it's job. The array which I want it to be sorted is randomly generated. I read from a file the number of elements the array will have and the maximum value and then create the list.

def mergeSort(listaNumere):
    n = len(listaNumere)
    if n == 1:
        return listaNumere
    mij = n//2
    stanga = []
    for i in range (0, mij):
        stanga.append(listaNumere[i])
    dreapta = []
    for i in range(mij, n):
        dreapta.append(listaNumere[i])

    #stanga = listaNumere[:mij]
    #dreapta = listaNumere[mij:]

    stanga = mergeSort(stanga)
    dreapta = mergeSort(dreapta)

    return merge(stanga, dreapta)

def merge(stanga, dreapta):
    aux = []
    while len(stanga) != 0 and len(dreapta) != 0:
        if stanga[0] < dreapta[0]:
            aux.append(stanga[0])
            del stanga[0]
        else:
            aux.append(dreapta[0])
            del dreapta[0]

    while len(stanga) != 0:
        aux.append(stanga[0])
        del stanga[0]

    while len(dreapta) != 0:
        aux.append(dreapta[0])
        del dreapta[0]

    return aux

The program has been running in the background for the past 30 minutes and has not finished sorting the array.

How can i make the program more efficient so that it does not take that much time to run?

Tried this:

def merge(stanga, dreapta):
    aux = []
    i,j = 0,0
    while i < len(stanga) and j < len(dreapta):
        if stanga[i] < dreapta[j]:
            aux.append(stanga[i])
            i  = 1
        else:
            aux.append(dreapta[j])
            j  = 1

    while i < len(stanga):
        aux.append(stanga[i])
        i  = 1

    while j < len(dreapta):
        aux.append(dreapta[i])
        i  = 1

    return aux

CodePudding user response:

Delete operation has O(N) complexity, which will inevitably make program execution very slow.
Get rid of all del dreapta[0] and del stanga[0] statements and refactor your merge logic using two pointers.

def merge(stanga, dreapta):
    aux = []
    i,j = 0,0
    while i < len(stanga) and j < len(dreapta):
        if stanga[i] < dreapta[j]:
...

CodePudding user response:

Make a one time copy of the array. Alternate direction of merge with level of recursion to avoid excess copying of data. This example code takes a bit over 1 minute to sort 10^7 integers. This is a case where Python is slow. The same code in C | C is over 50 times faster.

def sort(a):
    if(len(a) < 2):                     # if nothing to do, return
        return
    b = a[:]                            # b = copy of a
    sortr(b, a, 0, len(a))              # merge sort

def sortr(b, a, beg, end):              # merge sort
    if((end - beg) < 2):                # if < 2 elements
        return                          #   return
    mid = (beg end)//2                  # set mid point
    sortr(a, b, beg, mid)               # merge sort left  half to b
    sortr(a, b, mid, end)               # merge sort right half to b
    mrg(b, a, beg, mid, end)            # merge halves   from b to a

def mrg(a, b, ll, rr, ee):              # merge a pair of runs from a to b
    o = ll                              # o = b[]        index
    l = ll                              # l = a[] left   index
    r = rr                              # r = a[] right  index
    while True:
        if(a[l] <= a[r]):               # if a[l] <= a[r]
            b[o] = a[l]                 #   copy a[l]
            o  = 1
            l  = 1
            if(l < rr):                 #   if not end of left run
                continue                #     continue (back to while)
            b[o:ee] = a[r:ee]           #   else copy rest of right run
            return                      #     and return
        else:                           # else a[l] > a[r]
            b[o] = a[r]                 #   copy a[r]
            o  = 1
            r  = 1
            if(r < ee):                 #   if not end of right run
                continue                #     continue (back to while)
            b[o:ee] = a[l:rr]           #   else copy rest of left run
            return                      #     and return
  • Related