Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Код лаб / lab2

.py
Скачиваний:
0
Добавлен:
28.12.2024
Размер:
6.83 Кб
Скачать
#from array import array
import ctypes
from LinkedList import LinkedList
from ArrayList import ArrayList
import random
from MergeSort import MergeSort
from InsertionSort import InsertionSort
from Notation import Stack
import bisect
from datetime import datetime
import time

MIN_MINRUN = 32
def temp_array(array, s_ind, e_ind):
  temp_array = []
  while s_ind <= e_ind:
    temp_array.append(array.get(s_ind))
    s_ind += 1
  return temp_array
def find_run(array, s_ind):
  incr = True

  if s_ind == array.size() - 1:   #s_ind = end_ind
    return [s_ind, s_ind, incr, 1]
  else:
    e_ind = s_ind
    
    if array.get(s_ind) > array.get(s_ind+1):
      while array.get(e_ind) > array.get(e_ind+1):
        e_ind += 1
        if e_ind == array.size() - 1:
          break  
      incr = False
      return [s_ind, e_ind, incr, e_ind - s_ind + 1]

    else:
      while array.get(e_ind) <= array.get(e_ind + 1):
        e_ind += 1
        if e_ind == array.size() - 1:
          break

        return [s_ind, e_ind, incr, e_ind - s_ind + 1]
  


def reverse(array, s_ind, e_ind):
  while s_ind < e_ind and s_ind != e_ind:
    array.set(s_ind, array.get(e_ind))
    array.set(e_ind, array.get(s_ind))
    s_ind += 1
    e_ind -= 1


def gallop_tmp(lst, value, s_ind, e_ind):
  position = bisect.bisect_left(lst, value, s_ind, e_ind)
  return position
def gallop_arr(array, value, s_ind, e_ind):
  list = []
  for i in range(array.size()):
    list.append(array.get(i))
  position = bisect.bisect_left(list, value, s_ind, e_ind)
  return position
def MinRun(n):
  r = 0
  while n >= MIN_MINRUN:
    r |= n & 1
    n >>= 1
  return n + r
def merge_low(array, a, b, min_g):
  #fgfdg
  #a and b - list of runs
  tmp_array = temp_array(array, a[0], a[1])
  i = 0  #counter of temp array
  j = b[0] #pointer for b
  f_ind = a[0] #first_ind
  gallop = min_g
  while True:
    a_count = 0
    b_count = 0

    while i <= len(tmp_array) - 1 and j <= b[1]:
      if tmp_array[i] <= array.get(j):
        array.set(f_ind, tmp_array[i])
        f_ind += 1
        i += 1
        a_count += 1
        b_count = 0
      
        if i > len(tmp_array) - 1:
          while j <= b[1]:
            array.set(f_ind, array.get(j))
            f_ind += 1
            j += 1
          return
        if a_count >= gallop: #switch to gallop
          break
      else:
        array.set(f_ind, array.get(j))
        f_ind += 1
        j += 1

        a_count = 0
        b_count += 1
      
        if j > b[1]: #if list run out
          while i <= len(tmp_array) - 1:
            array.set(f_ind, tmp_array[i])
            f_ind += 1
            i += 1
          return
        if b_count >= gallop:
          break
    while True:
      pos_a = gallop_tmp(tmp_array, array.get(j), i, len(tmp_array))
      for x in range(i, pos_a):
        array.set(f_ind, tmp_array[x])
        f_ind += 1
      a_count = pos_a - i
      i = pos_a

      if i > len(tmp_array) - 1:  #if a runs out
        while j <= b[1]:
          array.set(f_ind, array.get(j))
          f_ind += 1
          j += 1
        return
      array.set(f_ind, array.get(j))
      f_ind += 1
      j += 1

      if j > b[1]:
        while i < len(tmp_array):
          array.set(f_ind, tmp_array[i])
          f_ind += 1
          i+= 1
        return

      pos_b = gallop_arr(array, tmp_array[i], j, b[1] + 1)
      for y in range(j, pos_b):
        array.set(f_ind, array.get(y))
        f_ind += 1

      b_count = pos_b - j
      j = pos_b

      if j > b[1]:
        while i <= len(temp_array) - 1:
          array.set(f_ind, temp_array[i])
          f_ind += 1
          i += 1
        return

        array.set(f_ind, temp_array[i])
        i += 1
        f_ind += 1

        if i > len(temp_array) - 1:
          while j <= b[1]:
            array.set(f_ind, array.get(j))
            f_ind += 1
            j += 1
          return
      
      if a_count < gallop and b_count < gallop:
        break
    gallop += 1
  
def merge_high(array, a, b, min_g):
  #fgfdg
  #a and b - list of runs
  tmp_array = temp_array(array, b[0], b[1])
  i = len(tmp_array) - 1  #counter of temp array
  j = a[1] #pointer for b
  f_ind = b[1] #first_ind
  gallop = min_g

  a_count = 0
  b_count = 0

  while  i >= 0 and j >= a[0]:
    if tmp_array[i] > array.get(j):
      array.set(f_ind, tmp_array[i])
      f_ind -= 1
      i -= 1
      a_count = 0
      b_count += 1
      
      if i < 0:
        while j >= a[0]:
          array.set(f_ind, array.get(j))
          f_ind -= 1
          j -= 1
        return
      #if a_count >= gallop: #switch to gallop
        #break
    else:
      array.set(f_ind, array.get(j))
      f_ind -= 1
      j -= 1

      a_count += 1
      b_count = 0
      
      if j < a[0]: #if list run out
        while i >= 0:
          array.set(f_ind, tmp_array[i])
          f_ind -= 1
          i -= 1
        return
      #if b_count >= gallop:
        #break
        
def merge(array, stack, run_num):
  run_a = stack[run_num]
  run_b = stack[run_num + 1]
  new_run = [run_a[0], run_b[1], True, run_b[1] - run_a[0] + 1]

  stack[run_num] = new_run

  del stack[run_num + 1]
  #if run_a[3] <= run_b[3]:
   # merge_low(array, run_a, run_b, 7)
  #else:
   # merge_high(array, run_a, run_b, 7)
  merge_low(array, run_a, run_b, 7)
def m_collapse(array,stack):
  # Z > Y + X
  # Y > X
  #stack[-3] > stack[-2] + stack[-1]
  #stack[-2] > stack[-1]
  while len(stack) > 1:
    if len(stack) >= 3 and stack[-3][3] <= stack[-2][3] + stack[-1][3]:
      if stack[-3][3] < stack[-1][3]:
        merge(array, stack, -3)
      else:
        merge(array, stack, -2)
    elif stack[-2][3] <= stack[-1][3]:
      merge(array, stack, -2)
    else:
      break    
def m_end_collapse(array, stack):
  while len(stack) > 1:
    merge(array, stack, -2)
def TimSort(array):
  n = array.size()
  minrun = MinRun(n)

  stack = []
  s_ind = 0
  e_ind = array.size()-1 

  while s_ind <= e_ind:

    run = find_run(array, s_ind)

    if run[2] == False:
      reverse(array, run[0], run[1])
      run[2] = True

    if run[3] < minrun:
      extend = min(minrun - run[3], e_ind - run[1])
      run[1] += extend
      run[3] += extend
      InsertionSort(array, run[0], run[1])
      
    stack.append(run)
    m_collapse(array, stack)
    #array.out()
    s_ind = run[1] + 1

  m_end_collapse(array, stack)
  #array.out()
  return array

myList = ArrayList()
myList1 = ArrayList()
myList2 = ArrayList()
for i in range(100):
  myList.add(random.randint(0, 1000))
  myList1.add(myList.get(i))
  myList2.add(myList.get(i))
#myList.out()
start_time = datetime.now()
TimSort(myList)
print(datetime.now() - start_time)
start_time = datetime.now()
MergeSort(myList1)
print(datetime.now() - start_time)
start_time = datetime.now()
InsertionSort(myList2)
print(datetime.now() - start_time)
Соседние файлы в папке Код лаб