mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-12-18 01:00:15 +00:00
Add Merge Sort Linked List algorithm
This commit is contained in:
parent
a9ca110d6b
commit
121bfdae5f
168
data_structures/linked_list/merge_sort_linked_list.py
Normal file
168
data_structures/linked_list/merge_sort_linked_list.py
Normal file
|
@ -0,0 +1,168 @@
|
|||
class Node:
|
||||
"""
|
||||
A class representing a node in a linked list.
|
||||
|
||||
Attributes:
|
||||
data (int): The data stored in the node.
|
||||
next (Node | None): A reference to the next node in the linked list.
|
||||
|
||||
>>> head = Node(4)
|
||||
>>> head.next = Node(2)
|
||||
>>> head.next.next = Node(1)
|
||||
>>> head.next.next.next = Node(3)
|
||||
>>> sorted_head = merge_sort_linked_list(head)
|
||||
>>> print_linked_list(sorted_head)
|
||||
1 2 3 4
|
||||
"""
|
||||
|
||||
def __init__(self, data: int):
|
||||
self.data = data
|
||||
self.next: Node | None = None
|
||||
|
||||
|
||||
def get_middle(head: Node) -> Node:
|
||||
"""
|
||||
Find the middle node of the linked list using the slow and fast pointer technique.
|
||||
|
||||
Parameters:
|
||||
head: The head node of the linked list.
|
||||
|
||||
Returns:
|
||||
The middle node of the linked list.
|
||||
|
||||
Example:
|
||||
>>> head = Node(1)
|
||||
>>> head.next = Node(2)
|
||||
>>> head.next.next = Node(3)
|
||||
>>> get_middle(head).data
|
||||
2
|
||||
"""
|
||||
|
||||
if head is None:
|
||||
return head
|
||||
|
||||
slow = head # one node at a time
|
||||
fast = head # two nodes at a time
|
||||
while fast.next and fast.next.next:
|
||||
slow = slow.next
|
||||
fast = fast.next.next
|
||||
return slow
|
||||
|
||||
|
||||
def merge(left: Node | None, right: Node | None) -> Node | None:
|
||||
"""
|
||||
Merge two sorted linked lists into one sorted linked list.
|
||||
|
||||
Parameters:
|
||||
left: The head of the first sorted linked list.
|
||||
right: The head of the second sorted linked list.
|
||||
|
||||
Returns:
|
||||
The head of the merged sorted linked list.
|
||||
|
||||
Example:
|
||||
>>> left = Node(1)
|
||||
>>> left.next = Node(3)
|
||||
>>> right = Node(2)
|
||||
>>> right.next = Node(4)
|
||||
>>> merged = merge(left, right)
|
||||
>>> print_linked_list(merged)
|
||||
1 2 3 4
|
||||
"""
|
||||
|
||||
if left is None:
|
||||
return right
|
||||
if right is None:
|
||||
return left
|
||||
|
||||
if left.data <= right.data:
|
||||
result = left
|
||||
result.next = merge(left.next, right)
|
||||
else:
|
||||
result = right
|
||||
result.next = merge(left, right.next)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def print_linked_list(head: Node | None) -> None:
|
||||
"""
|
||||
Print the linked list in a single line.
|
||||
|
||||
Parameters:
|
||||
head: The head node of the linked list.
|
||||
|
||||
Example:
|
||||
>>> head = Node(1)
|
||||
>>> head.next = Node(2)
|
||||
>>> head.next.next = Node(3)
|
||||
>>> print_linked_list(head)
|
||||
1 2 3
|
||||
"""
|
||||
|
||||
current = head
|
||||
first = True # To avoid printing space before the first element
|
||||
while current:
|
||||
if not first:
|
||||
print(" ", end="")
|
||||
print(current.data, end="")
|
||||
first = False
|
||||
current = current.next
|
||||
print()
|
||||
|
||||
|
||||
def merge_sort_linked_list(head: Node | None) -> Node | None:
|
||||
"""
|
||||
Sort a linked list using the Merge Sort algorithm.
|
||||
|
||||
Parameters:
|
||||
head: The head node of the linked list to be sorted.
|
||||
|
||||
Returns:
|
||||
The head node of the sorted linked list.
|
||||
|
||||
Example:
|
||||
>>> head = Node(4)
|
||||
>>> head.next = Node(2)
|
||||
>>> head.next.next = Node(1)
|
||||
>>> head.next.next.next = Node(3)
|
||||
>>> sorted_head = merge_sort_linked_list(head)
|
||||
>>> print_linked_list(sorted_head)
|
||||
1 2 3 4
|
||||
|
||||
>>> head = Node(1)
|
||||
>>> head.next = Node(2)
|
||||
>>> head.next.next = Node(3)
|
||||
>>> head.next.next.next = Node(4)
|
||||
>>> sorted_head = merge_sort_linked_list(head)
|
||||
>>> print_linked_list(sorted_head)
|
||||
1 2 3 4
|
||||
|
||||
>>> head = Node(10)
|
||||
>>> head.next = Node(3)
|
||||
>>> head.next.next = Node(5)
|
||||
>>> head.next.next.next = Node(1)
|
||||
>>> sorted_head = merge_sort_linked_list(head)
|
||||
>>> print_linked_list(sorted_head)
|
||||
1 3 5 10
|
||||
"""
|
||||
|
||||
# Base Case: 0 or 1 node
|
||||
if head is None or head.next is None:
|
||||
return head
|
||||
|
||||
# Split the linked list into two halves
|
||||
middle = get_middle(head)
|
||||
next_to_middle = middle.next
|
||||
middle.next = None # Split the list into two parts
|
||||
|
||||
left = merge_sort_linked_list(head) # Sort the left half
|
||||
right = merge_sort_linked_list(next_to_middle) # Sort the right half
|
||||
sorted_list = merge(left, right) # Merge the sorted halves
|
||||
return sorted_list
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
Loading…
Reference in New Issue
Block a user