467 lines
17 KiB
Python
467 lines
17 KiB
Python
import random as rnd
|
|
import time
|
|
import csv
|
|
#############################################################################################
|
|
|
|
def sort_list(name_list):
|
|
l = len(name_list)
|
|
for i in range(l - 1):
|
|
for j in range(l - i - 1):
|
|
if name_list[j][0] > name_list[j + 1][0]:
|
|
name_list[j], name_list[j + 1] = name_list[j + 1], name_list[j]
|
|
return name_list
|
|
|
|
def hash_key(name):
|
|
h_key = sum(ord(ch) for ch in name)
|
|
return h_key
|
|
|
|
def create_name_phone(i):
|
|
name = f"User_{i:03d}"
|
|
phone = f"{rnd.randint(100, 999)}-{rnd.randint(100, 999)}"
|
|
return (name, phone)
|
|
|
|
def file_insert(results):
|
|
with open("results.csv", "w", encoding = "utf-8-sig", newline = "") as file:
|
|
writer = csv.writer(file)
|
|
writer.writerows(results)
|
|
###########################################################################################################################
|
|
|
|
def ll_insert(head, name, phone):
|
|
next_node = {'name': name, 'phone': phone, 'next': None}
|
|
if head is None: return next_node
|
|
|
|
running = head
|
|
while running is not None:
|
|
if running['name'] == name:
|
|
running['phone'] = phone
|
|
return head
|
|
running = running['next']
|
|
|
|
running = head
|
|
while running['next'] is not None: running = running['next']
|
|
running['next'] = next_node
|
|
return head
|
|
|
|
def ll_find(head, name):
|
|
running = head
|
|
|
|
while True:
|
|
if running['name'] == name:
|
|
return running['phone']
|
|
running = running['next']
|
|
if running is None: break
|
|
|
|
return None
|
|
|
|
|
|
def ll_delete(head, name):
|
|
running = head
|
|
|
|
if running['name'] == name:
|
|
return head['next']
|
|
|
|
while running['next']['name'] != name:
|
|
running = running['next']
|
|
if running['next']['next'] is None:
|
|
if running['next']['name'] != name:
|
|
return head
|
|
if running['next']['next'] is None:
|
|
running['next'] = None
|
|
else: running['next'] = running['next']['next']
|
|
|
|
return head
|
|
|
|
|
|
def ll_list_all(head):
|
|
name_list = []
|
|
running = head
|
|
while running is not None:
|
|
name_list.append((running['name'], running['phone']))
|
|
running = running['next']
|
|
return name_list
|
|
|
|
################################################################################################################################
|
|
|
|
|
|
def LinkedList(head, phone_book):
|
|
|
|
start_insert = time.perf_counter()
|
|
for i in range(len(phone_book)):
|
|
|
|
head = ll_insert(head, phone_book[i][0], phone_book[i][1])
|
|
#print(head)
|
|
end_insert = time.perf_counter()
|
|
time_insert = end_insert - start_insert
|
|
|
|
start_find = time.perf_counter()
|
|
for _ in range(100):
|
|
name = create_name_phone(rnd.randint(0, 999))[0]
|
|
phone = ll_find(head, name)
|
|
#print(name, ":", phone)
|
|
end_find = time.perf_counter()
|
|
time_find = end_find - start_find
|
|
|
|
|
|
start_delete = time.perf_counter()
|
|
for i in range(110):
|
|
if i <= 99: name = f"User_{rnd.randint(0,999):03d}"
|
|
else: name = f"None_{i:03d}"
|
|
head = ll_delete(head, name)
|
|
end_delete = time.perf_counter()
|
|
time_delete = end_delete - start_delete
|
|
|
|
|
|
start_list = time.perf_counter()
|
|
name_list = sort_list(ll_list_all(head))
|
|
#print(*name_list)
|
|
end_list = time.perf_counter()
|
|
time_list = end_list - start_list
|
|
|
|
return (time_insert, time_find, time_delete, time_list)
|
|
|
|
#########################################################################################################
|
|
|
|
def ht_insert(buckest, name, phone):
|
|
index = hash_key(name) % 10
|
|
for i, (Name, Phone) in enumerate(buckest[index]):
|
|
if Name == name:
|
|
buckest[index][i] = (name, phone)
|
|
return buckest
|
|
buckest[index].append((name, phone))
|
|
return buckest
|
|
|
|
def ht_find(buckest, name):
|
|
index = hash_key(name) % 10
|
|
for (Name, Phone) in buckest[index]:
|
|
if Name == name:
|
|
return Phone
|
|
return None
|
|
|
|
def ht_list_all(buckest):
|
|
|
|
name_list = []
|
|
|
|
for index in range(len(buckest)):
|
|
for i, (name, phone) in enumerate(buckest[index]):
|
|
name_list.append((name, phone))
|
|
|
|
name_list = sort_list(name_list)
|
|
|
|
return name_list
|
|
|
|
|
|
def ht_delete(buckest, name):
|
|
index = hash_key(name) % 10
|
|
for i, (Name, Phone) in enumerate(buckest[index]):
|
|
if Name == name:
|
|
del buckest[index][i]
|
|
return buckest
|
|
|
|
|
|
####################################################################################################
|
|
|
|
def HashTable(buckest, phone_book):
|
|
|
|
|
|
start_insert = time.perf_counter()
|
|
for i in range(len(phone_book)):
|
|
|
|
buckest = ht_insert(buckest, phone_book[i][0], phone_book[i][1])
|
|
#print(buckest)
|
|
end_insert = time.perf_counter()
|
|
time_insert = end_insert - start_insert
|
|
|
|
|
|
start_find = time.perf_counter()
|
|
for _ in range(100):
|
|
name = create_name_phone(rnd.randint(0, 999))[0]
|
|
phone = ht_find(buckest, name)
|
|
#print(name, ":", phone)
|
|
end_find = time.perf_counter()
|
|
time_find = end_find - start_find
|
|
|
|
|
|
start_delete = time.perf_counter()
|
|
for i in range(110):
|
|
if i <= 99: name = f"User_{rnd.randint(0,999):03d}"
|
|
else: name = f"None_{i:03d}"
|
|
buckest = ht_delete(buckest, name)
|
|
end_delete = time.perf_counter()
|
|
time_delete = end_delete - start_delete
|
|
|
|
|
|
start_list = time.perf_counter()
|
|
name_list = sort_list(ht_list_all(buckest))
|
|
#print(*name_list)
|
|
end_list = time.perf_counter()
|
|
time_list = end_list - start_list
|
|
|
|
return (time_insert, time_find, time_delete, time_list)
|
|
|
|
#################################################################################################
|
|
|
|
def bst_insert(root, name, phone):
|
|
|
|
running = root
|
|
|
|
if running is None:
|
|
root = {'name': name, 'phone': phone, 'left': None, 'right': None}
|
|
return root
|
|
while True:
|
|
node = hash_key(running['name'])
|
|
sheet = hash_key(name)
|
|
if node < sheet:
|
|
if running['right'] is None:
|
|
running['right'] = {'name': name, 'phone': phone, 'left': None, 'right': None}
|
|
return root
|
|
running = running['right']
|
|
elif node > sheet:
|
|
if running['left'] is None:
|
|
running['left'] = {'name': name, 'phone': phone, 'left': None, 'right': None}
|
|
return root
|
|
running = running['left']
|
|
else:
|
|
running['phone'] = phone
|
|
return root
|
|
|
|
def bst_find(root, name):
|
|
|
|
running = root
|
|
|
|
while running is not None:
|
|
node = hash_key(running['name'])
|
|
sheet = hash_key(name)
|
|
if name == running['name']:
|
|
return running['phone']
|
|
elif node < sheet:
|
|
running = running['right']
|
|
else:
|
|
running = running['left']
|
|
|
|
return None
|
|
|
|
def bst_list_all(root, name_list = []):
|
|
if root is None:
|
|
return
|
|
name_list.append((root['name'], root['phone']))
|
|
bst_list_all(root['left'], name_list)
|
|
bst_list_all(root['right'], name_list)
|
|
name_list = sort_list(name_list)
|
|
return name_list
|
|
|
|
def bst_delete(root, name):
|
|
|
|
if root is None:
|
|
return None
|
|
if hash_key(name) < hash_key(root['name']):
|
|
root['left'] = bst_delete(root['left'], name)
|
|
elif hash_key(name) > hash_key(root['name']):
|
|
root['right'] = bst_delete(root['right'], name)
|
|
else:
|
|
|
|
if root['left'] is None and root['right'] is None:
|
|
return None
|
|
|
|
if root['left'] is None:
|
|
return root['right']
|
|
if root['right'] is None:
|
|
return root['left']
|
|
|
|
min_node = root['right']
|
|
while min_node['left'] is not None:
|
|
min_node = min_node['left']
|
|
|
|
root['name'] = min_node['name']
|
|
root['phone'] = min_node['phone']
|
|
|
|
root['right'] = bst_delete(root['right'], min_node['name'])
|
|
|
|
return root
|
|
|
|
#################################################################################################
|
|
|
|
def BinarySearchTree(root, phone_book):
|
|
|
|
start_insert = time.perf_counter()
|
|
for i in range(len(phone_book)):
|
|
|
|
root = bst_insert(root, phone_book[i][0], phone_book[i][1])
|
|
#print(buckest)
|
|
end_insert = time.perf_counter()
|
|
time_insert = end_insert - start_insert
|
|
|
|
|
|
start_find = time.perf_counter()
|
|
for _ in range(100):
|
|
name = create_name_phone(rnd.randint(0, 999))[0]
|
|
phone = bst_find(root, name)
|
|
#print(name, ":", phone)
|
|
end_find = time.perf_counter()
|
|
time_find = end_find - start_find
|
|
|
|
|
|
start_delete = time.perf_counter()
|
|
for i in range(110):
|
|
if i <= 99: name = f"User_{rnd.randint(0,999):03d}"
|
|
else: name = f"None_{i:03d}"
|
|
root = bst_delete(root, name)
|
|
end_delete = time.perf_counter()
|
|
time_delete = end_delete - start_delete
|
|
|
|
|
|
start_list = time.perf_counter()
|
|
name_list = sort_list(bst_list_all(root))
|
|
#print(*name_list)
|
|
end_list = time.perf_counter()
|
|
time_list = end_list - start_list
|
|
|
|
return (time_insert, time_find, time_delete, time_list)
|
|
|
|
################################################################################################
|
|
def main():
|
|
|
|
phone_book = []
|
|
for i in range(1000):
|
|
phone_book.append(create_name_phone(i))
|
|
for _ in range(9000):
|
|
phone_book.append(create_name_phone(rnd.randint(0, 999)))
|
|
|
|
phone_book_not_sorted = phone_book.copy()
|
|
rnd.shuffle(phone_book_not_sorted)
|
|
|
|
phone_book_sorted = phone_book.copy()
|
|
phone_book_sorted = sort_list(phone_book_sorted)
|
|
replay = 5
|
|
|
|
|
|
Time_ll_not_sorted = []
|
|
Time_ll_sorted = []
|
|
|
|
Time_average_ll_not_sorted = {'insert': 0, 'find': 0, 'delete': 0, 'list': 0}
|
|
Time_average_ll_sorted = {'insert': 0, 'find': 0, 'delete': 0, 'list': 0}
|
|
|
|
print("============================================ TESTING LINKEDLIST =====================================\n")
|
|
print('Not sorted: ')
|
|
for _ in range(replay):
|
|
time_ll_not_sorted = LinkedList(None, phone_book_not_sorted)
|
|
Time_ll_not_sorted.append({'insert': time_ll_not_sorted[0], 'find': time_ll_not_sorted[1], 'delete': time_ll_not_sorted[2], 'list': time_ll_not_sorted[3]})
|
|
for i, key in enumerate(Time_average_ll_not_sorted):
|
|
Time_average_ll_not_sorted[key] += time_ll_not_sorted[i]/replay
|
|
for i in range(replay):
|
|
print(Time_ll_not_sorted[i])
|
|
print("Average:", Time_average_ll_not_sorted, "\n\n")
|
|
|
|
print('Sorted:')
|
|
for _ in range(replay):
|
|
time_ll_sorted = LinkedList(None, phone_book_sorted)
|
|
Time_ll_sorted.append({'insert': time_ll_sorted[0], 'find': time_ll_sorted[1], 'delete': time_ll_sorted[2], 'list': time_ll_sorted[3]})
|
|
for i, key in enumerate(Time_average_ll_sorted):
|
|
Time_average_ll_sorted[key] += time_ll_sorted[i]/replay
|
|
for i in range(replay):
|
|
print(Time_ll_not_sorted[i])
|
|
print("Average:", Time_average_ll_sorted, "\n\n")
|
|
|
|
|
|
|
|
Time_ht_not_sorted = []
|
|
Time_ht_sorted = []
|
|
|
|
Time_average_ht_not_sorted = {'insert': 0, 'find': 0, 'delete': 0, 'list': 0}
|
|
Time_average_ht_sorted = {'insert': 0, 'find': 0, 'delete': 0, 'list': 0}
|
|
|
|
print("============================================ TESTING HASHTABLE =====================================\n")
|
|
print('Not sorted: ')
|
|
for _ in range(replay):
|
|
time_ht_not_sorted = HashTable([[] for _ in range(100)], phone_book_not_sorted)
|
|
Time_ht_not_sorted.append({'insert': time_ht_not_sorted[0], 'find': time_ht_not_sorted[1], 'delete': time_ht_not_sorted[2], 'list': time_ht_not_sorted[3]})
|
|
for i, key in enumerate(Time_average_ht_not_sorted):
|
|
Time_average_ht_not_sorted[key] += time_ht_not_sorted[i]/replay
|
|
for i in range(replay):
|
|
print(Time_ht_not_sorted[i])
|
|
print(f"Average: {Time_average_ht_not_sorted}\n\n")
|
|
|
|
print('Sorted: ')
|
|
for _ in range(replay):
|
|
time_ht_sorted = HashTable([[] for _ in range(100)], phone_book_sorted)
|
|
Time_ht_sorted.append({'insert': time_ht_sorted[0], 'find': time_ht_sorted[1], 'delete': time_ht_sorted[2], 'list': time_ht_sorted[3]})
|
|
for i, key in enumerate(Time_average_ht_sorted):
|
|
Time_average_ht_sorted[key] += time_ht_sorted[i]/replay
|
|
for i in range(replay):
|
|
print(Time_ht_sorted[i])
|
|
print(f"Average: {Time_average_ht_sorted}\n\n")
|
|
|
|
|
|
|
|
Time_bst_not_sorted = []
|
|
Time_bst_sorted = []
|
|
|
|
Time_average_bst_not_sorted = {'insert': 0, 'find': 0, 'delete': 0, 'list': 0}
|
|
Time_average_bst_sorted = {'insert': 0, 'find': 0, 'delete': 0, 'list': 0}
|
|
|
|
print("============================================ TESTING BINARYSEARCHTREE =====================================\n")
|
|
print('Not sorted: ')
|
|
for _ in range(replay):
|
|
time_bst_not_sorted = BinarySearchTree(None, phone_book_not_sorted)
|
|
Time_bst_not_sorted.append({'insert': time_bst_not_sorted[0], 'find': time_bst_not_sorted[1], 'delete': time_bst_not_sorted[2], 'list': time_bst_not_sorted[3]})
|
|
for i, key in enumerate(Time_average_bst_not_sorted):
|
|
Time_average_bst_not_sorted[key] += time_bst_not_sorted[i]/replay
|
|
for i in range(replay):
|
|
print(Time_bst_not_sorted[i])
|
|
print(f"Average: {Time_average_bst_not_sorted}\n\n")
|
|
|
|
print('Sorted: ')
|
|
for _ in range(replay):
|
|
time_bst_sorted = BinarySearchTree(None, phone_book_sorted)
|
|
Time_bst_sorted.append({'insert': time_bst_sorted[0], 'find': time_bst_sorted[1], 'delete': time_bst_sorted[2], 'list': time_bst_sorted[3]})
|
|
for i, key in enumerate(Time_average_bst_sorted):
|
|
Time_average_bst_sorted[key] += time_bst_sorted[i]/replay
|
|
for i in range(replay):
|
|
print(Time_bst_sorted[i])
|
|
print(f"Average: {Time_average_bst_sorted}\n\n")
|
|
print("=============================================== END TESTING ================================================")
|
|
|
|
results = [["Структура", "Режим", "Операция", "Время(мс)"]]
|
|
for i in range(replay):
|
|
results.append(["LinkedList", "Случайный", "вставка", Time_ll_not_sorted[i]["insert"]])
|
|
results.append(["LinkedList", "Случайный", "поиск", Time_ll_not_sorted[i]["find"]])
|
|
results.append(["LinkedList", "Случайный", "удаление", Time_ll_not_sorted[i]["delete"]])
|
|
results.append(["LinkedList", "Случайный", "формирование списка", Time_ll_not_sorted[i]["list"]])
|
|
|
|
results.append(["LinkedList", "Упорядоченный", "вставка", Time_ll_sorted[i]["insert"]])
|
|
results.append(["LinkedList", "Упорядоченный", "поиск", Time_ll_sorted[i]["find"]])
|
|
results.append(["LinkedList", "Упорядоченный", "удаление", Time_ll_sorted[i]["delete"]])
|
|
results.append(["LinkedList", "Упорядоченный", "формирование списка", Time_ll_sorted[i]["list"]])
|
|
|
|
for i in range(replay):
|
|
results.append(["HashTable", "Случайный", "вставка", Time_ht_not_sorted[i]["insert"]])
|
|
results.append(["HashTable", "Случайный", "поиск", Time_ht_not_sorted[i]["find"]])
|
|
results.append(["HashTable", "Случайный", "удаление", Time_ht_not_sorted[i]["delete"]])
|
|
results.append(["HashTable", "Случайный", "формирование списка", Time_ht_not_sorted[i]["list"]])
|
|
|
|
results.append(["HashTable", "Упорядоченный", "вставка", Time_ht_sorted[i]["insert"]])
|
|
results.append(["HashTable", "Упорядоченный", "поиск", Time_ht_sorted[i]["find"]])
|
|
results.append(["HashTable", "Упорядоченный", "удаление", Time_ht_sorted[i]["delete"]])
|
|
results.append(["HashTable", "Упорядоченный", "формирование списка", Time_ht_sorted[i]["list"]])
|
|
|
|
for i in range(replay):
|
|
results.append(["BinarySearchTree", "Случайный", "вставка", Time_bst_not_sorted[i]["insert"]])
|
|
results.append(["BinarySearchTree", "Случайный", "поиск", Time_bst_not_sorted[i]["find"]])
|
|
results.append(["BinarySearchTree", "Случайный", "удаление", Time_bst_not_sorted[i]["delete"]])
|
|
results.append(["BinarySearchTree", "Случайный", "формирование списка", Time_bst_not_sorted[i]["list"]])
|
|
|
|
results.append(["BinarySearchTree", "Упорядоченный", "вставка", Time_bst_sorted[i]["insert"]])
|
|
results.append(["BinarySearchTree", "Упорядоченный", "поиск", Time_bst_sorted[i]["find"]])
|
|
results.append(["BinarySearchTree", "Упорядоченный", "удаление", Time_bst_sorted[i]["delete"]])
|
|
results.append(["BinarySearchTree", "Упорядоченный", "формирование списка", Time_bst_sorted[i]["list"]])
|
|
|
|
for i in range(1, len(results) - 1):
|
|
results[i][3] *= 1000
|
|
file_insert(results)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|
|
|
|
|
|
|