
Добавил:
linnesse
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Код лаб / lab2
.py#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)
Соседние файлы в папке Код лаб