# [completion algorithm] sorting of single linked list

Posted by RSprinkel on Mon, 08 Nov 2021 08:59:44 +0100

More algorithm solutions, please pay attention to the official account, "programmer"

## Sorting of single linked list

### Problem description

Given an unordered single linked list with n nodes, it is sorted in ascending order.

Requirements: space complexity O(n), time complexity O(nlogn).

Example:

Input: [- 1,0, - 2]

Return value: {- 2, - 1,0}

### Analyze problems

Because the topic requires that the time complexity is O(nlogn), the sorting algorithms with time complexity of O(nlogn) include merge sorting, quick sorting and heap sorting, among which the most suitable sorting algorithm for linked list is merge sorting.

Merge sort is based on the idea of divide and conquer. The easiest thing to think of is the top-down recursive implementation. The top-down recursive implementation mainly includes two links.

• Find the midpoint of the linked list, take the midpoint as the boundary, and split the linked list into two sub linked lists. The fast and slow pointer method can be used to find the midpoint of the linked list. The fast pointer moves 2 steps each time and the slow pointer moves 1 step each time. When the fast pointer reaches the end of the linked list, the slow pointer just points to the midpoint of the linked list.
• After finding the midpoint, cut the linked list into two sub linked lists at the midpoint.
• Then recursively split until the split linked list has only one node or is Null. At this time, the split sub linked list is ordered because it contains only one node.

• Merge two ordered linked lists into an ordered linked list. We can use the double finger needle method.
• Execute recursively until the merge is complete.

```class Solution:
#If the linked list is empty or contains only one node, recursion terminates
#Use the fast and slow pointer method to find the midpoint of the linked list
while fast and fast.next:
fast=fast.next.next
slow=slow.next
#slow points to the midpoint of the linked list. The linked list is divided at the midpoint
slow.next=None
#Merge the linked list and use the double finger needle method
tmp = res = ListNode(0)
while left and right:
if left.val < right.val:
tmp.next=left
left=left.next
else:
tmp.next=right
right=right.next
tmp=tmp.next
if left:
tmp.next=left
else:
tmp.next=right
return res.next```

The time complexity of the algorithm is O(n). Since top-down is implemented by recursion, if the stack space of recursive call stack is considered, the space complexity of the algorithm is O(logn).

### optimization

We can also use the bottom-up method to solve it.

First, we find the length of the linked list. Then split the linked list into sub linked lists for merging.

1. We use sublength to represent the length of the sub linked list to be sorted each time. Initially, sublength=1.
2. Each time, the linked list is divided into several sub linked lists with a length of sublength (the length of the last sub linked list may be less than sublength), and the two sub linked lists are combined as a group. After the combination, several ordered sub linked lists with a length of sublength 2 can be obtained (the length of the last sub linked list may be less than sublength 2).
3. Double the value of sublength, repeat the second step, and then merge the longer ordered sub linked list until the length of the ordered sub linked list is greater than or equal to the length of the linked list, so that the sorting of the whole linked list is completed.

Let's look at the implementation of the code.

```class Solution:
#Sentinel Nodes

else:
temp = temp.next
else:

#If the linked list is empty, return directly
#Traverse the linked list and find the length of the linked list
length = 0
while node:
length += 1
node = node.next

#Create a sentinel node that points to the chain header

#Initially, the length of the sub linked list is 1
subLength = 1

while subLength < length:

while cur:
for i in range(1, subLength):
if cur.next:
cur = cur.next
else:
break

cur.next = None

for i in range(1, subLength):
if cur and cur.next:
cur = cur.next
else:
break

#The remaining linked list nodes after interception
if cur:
cur.next = None