Python Algorithm -1-

Toku
Linked List
class Node:
def __init__(self, data, next_node=None):
self.data = data
self.next = next_node
class LinkedList:
def __init__(self, head=None) -> None:
self.head = head
def append(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
return
last_node = self.head
while last_node.next:
last_node = last_node.next
last_node.next = new_node
def insert(self, data):
new_node = Node(data)
new_node.next = self.head
self.head = new_node
def print(self) -> None:
current_node = self.head
while current_node:
print(current_node.data)
current_node = current_node.next
def remove(self, data) -> None:
import gc
current_node = self.head
if current_node and current_node.data == data:
self.head = current_node.next
# current_node = None
gc.collect()
return
previous_node = None
while current_node and current_node.data != data:
previous_node = current_node
current_node = current_node.next
if current_node is None:
return
previous_node.next = current_node.next
current_node = None
if __name__ == '__main__':
l = LinkedList()
l.append(1)
l.append(2)
l.append(3)
l.insert(0)
# l.print()
l.remove(2)
l.print()
# print(l.head.data)
# print(l.head.next.data)
# print(l.head.next.next.data)
Python Tutorials:Singly Linked List
https://www.youtube.com/watch?v=xRTdfZsAz6Y&t=666s
class Node:
def __init__(self, data):
self.data = data
self.ref = None
# node1 = Node(10)
# print(node1)
class LinkedList:
def __init__(self):
self.head = None
def print_LL(self):
if self.head == None:
print('linked list is empty!')
else:
n = self.head
while n is not None:
print(n.data)
n = n.ref
LL1 = LinkedList()
LL1.print_LL() // linked list is empty!
Inserting/Adding Elements At The Beginning Of The Linked List
https://www.youtube.com/watch?v=B-zO18TJKYQ&t=70s
def add_begin(self ,data):
new_node = Node(data)
new_node.ref = self.head
self.head = new_node
LL1 = LinkedList()
LL1.add_begin(10)
LL1.add_begin(20)
LL1.print_LL()
双方向リンクリスト
from __future__ import annotations
from typing import Any, Optional
class Node(object):
def __init__(self, data: Any, next_node: Node= None, prev_node: Node= None) -> None:
self.data = data
self.next = next_node
self.prev = prev_node
class DoublyLInkedList(object):
def __init__(self, head: Node = None) -> None:
self.head = head
def append(self, data:Any) -> None:
new_node = Node(data)
if self.head is None:
self.head = new_node
return
current_node = self.head
while current_node.next:
current_node = current_node.next
current_node.next = new_node
new_node.prev = current_node
def insert(self, data: Any) -> None:
new_node = Node(data)
if self.head is None:
self.head = new_node
return
self.head.prev = new_node
new_node.next = self.head
self.head = new_node
def print(self) -> None:
current_node = self.head
while current_node:
print(current_node.data)
current_node = current_node.next
def remove(self, data: Any) -> Node:
current_node = self.head
if current_node and current_node.data == data:
if current_node.next is None:
current_node = None
self.head = None
return
else:
next_node = current_node.next
next_node.prev = None
current_node = None
self.head = next_node
return
while current_node and current_node.data != data:
current_node = current_node.next
if current_node is None:
return # 一致するデータがなかった時
if current_node.next is None: #最後尾のNode
prev = current_node.prev
prev.next = None
current_node = None
return
else:
next_node = current_node.next # 中間にあるNode
prev_node = current_node.prev
prev_node.next = next_node
next_node.prev = prev_node
current_node = None
return
if __name__ == '__main__':
d = DoublyLInkedList()
d.append(0)
d.append(1)
d.append(2)
d.append(3)
d.print()
print("########")
d.remove(2)
d.print()
# print(d.head.data)
# print(d.head.next.data)
# print(d.head.next.next.data)
# print(d.head.next.next.next.data)
# print(d.head.next.next.prev.prev.data)
双方向リンクリストを逆方向に並び変える
def reverse_iterative(self) ->None:
previous_node = None
current_node = self.head
while current_node:
previous_node = current_node.prev
current_node.prev = current_node.next
current_node.next = previous_node
# 次のカレントノードに移る
current_node = current_node.prev
if previous_node:
self.head = previous_node.prev
def reverse_recursive(self) -> None:
def _reverse_recursive(current_node: Node) -> Optional[Node]:
if not current_node:
return Node
previous_node = current_node.prev
current_node.prev = current_node.next
current_node.next = previous_node
if current_node.prev is None:
return current_node
return _reverse_recursive(current_node.prev)
self.head = _reverse_recursive(self.head)
if __name__ == '__main__':
d = DoublyLInkedList()
d.append(0)
d.append(1)
d.append(2)
d.append(3)
d.print()
print("########")
# d.remove(2)
d.reverse_iterative()
d.print()
print("########")
d.reverse_recursive()
d.print()
ソートして並び替える
def sort(self)-> None:
if self.head is None:
return
current_node = self.head
# 1, 5, 2, 9
while current_node.next:
# print(current_node.data)
next_node = current_node.next
while next_node:
if current_node.data > next_node.data:
current_node.data, next_node.data = next_node.data, current_node.data
next_node = next_node.next
current_node = current_node.next
if __name__ == '__main__':
d = DoublyLInkedList()
d.append(1)
d.append(5)
d.append(2)
d.append(9)
d.print()
print("######## Sort")
d.sort()
d.print()
ハッシュテーブル
import hashlib
class HashTable(object):
def __init__(self, size = 10) -> None:
self.size = size
self.table = [ [] for _ in range(self.size)] #[[], [], [], [], []]
def hash(self, key) -> int:
return int(hashlib.md5(key.encode()).hexdigest(), base=16) % self.size
if __name__ == '__main__':
hash_table = HashTable()
print(hash_table.table)
print(hash_table.hash('car'))
user@mbp hash_table % python main.py
[[], [], [], [], [], [], [], [], [], []]
user@mbp hash_table % python
Python 3.10.3 (main, Apr 23 2022, 13:42:19) [Clang 13.1.6 (clang-1316.0.21.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import hashlib
>>> hashlib.md5('car')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Strings must be encoded before hashing
>>> hashlib.md5('car'.encode())
<md5 _hashlib.HASH object @ 0x102bd05d0>
>>> hashlib.md5('car'.encode()).hexdigest()
'e6d96502596d7e7887b76646c5f615d9'
>>> int(hashlib.md5('car'.encode()).hexdigest())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'e6d96502596d7e7887b76646c5f615d9'
>>> int(hashlib.md5('car'.encode()).hexdigest(), base=16)
306851216158335538240511469114392712665
carやPCなどある文字列を入力するとそれぞれ必ず同じ数列が戻ってくる
Pythonのforループでは、elseブロックを使用することができます。elseブロックは、forループが終了した後に実行されるコードブロックです。forループが正常に終了した場合にのみ実行され、breakステートメントによってループが中断された場合は実行されません。
fruits = ['apple', 'banana', 'orange']
for fruit in fruits:
if fruit == 'banana':
print("I found the banana!")
break
else:
print("The banana is not in the list.")
import hashlib
class HashTable(object):
def __init__(self, size = 10) -> None:
self.size = size
self.table = [ [] for _ in range(self.size)] #[[], [], [], [], []]
def hash(self, key) -> int:
return int(hashlib.md5(key.encode()).hexdigest(), base=16) % self.size
def add(self, key, value) -> None:
index = self.hash(key)
for data in self.table[index]:
if data[0] == key:
data[1] = value
break
else:
self.table[index].append([key, value])
if __name__ == '__main__':
hash_table = HashTable()
# print(hash_table.table)
# print(hash_table.hash('car'))
hash_table.add('car', 'Tesla')
hash_table.add('car', 'Toyota')
print(hash_table.table) # [[], [], [], [], [], [['car', 'Toyota']], [], [], [], []]
from typing import Anyは、PythonのtypingモジュールからAnyという型ヒントをインポートしていることを示します。
Anyは、Pythonの型ヒントの一つで、あらゆる型を表す特殊な型です。つまり、変数や関数の引数、戻り値などに対して「どんな型でも良い」という意味を持ちます。具体的な型を指定せずに柔軟性を持たせたい場合に使用されます。
例えば、以下のように関数の引数にAnyを指定することで、どんな型の引数でも受け入れることができます。
def print_value(value: Any) -> None:
print(value)
Getメソッドの作成
from typing import Any
def get(self, key) -> Any:
index = self.hash(key)
for data in self.table[index]:
if data[0] == key:
return data[1]
print(hash_table.get('car')) # Toyota
import hashlib
class HashTable(object):
def __init__(self, size = 10) -> None:
self.size = size
self.table = [ [] for _ in range(self.size)] #[[], [], [], [], []]
def hash(self, key) -> int:
return int(hashlib.md5(key.encode()).hexdigest(), base=16) % self.size
def add(self, key, value) -> None:
index = self.hash(key)
for data in self.table[index]:
if data[0] == key:
data[1] = value
break
else:
self.table[index].append([key, value])
def print(self) -> None:
for index in range(self.size):
print(index, end=' ') # 改行されなくなる
for data in self.table[index]:
print("===>", end=' ')
print(data, end=' ')
print()
from typing import Any
def get(self, key) -> Any:
index = self.hash(key)
for data in self.table[index]:
if data[0] == key:
return data[1]
# hash_table['car'] = 'Tesla' という形式で設定できる
def __setitem__(self, key, value) -> None:
self.add(key, value)
# hash_table['sns'] という形式で取得できる
def __getitem__(self, key):
return self.get(key)
if __name__ == '__main__':
hash_table = HashTable()
# print(hash_table.table)
# print(hash_table.hash('car'))
hash_table['car'] = 'Tesla'
hash_table.add('car', 'Toyota')
hash_table.add('pc', 'Mac')
hash_table.add('sns', 'Youtube')
# print(hash_table.table)
hash_table.print()
print(hash_table.get('car'))
print(hash_table['sns'])