链表的迭代归并排序
给定一个整数单链表,任务是使用迭代归并排序对其进行排序。
合并排序通常用于对链表进行排序。在这里讨论。但是,上面讨论的方法使用 Stack 来存储递归调用。如果要排序的链表太大,这可能会消耗大量内存。因此,本文讨论了一种纯迭代的归并排序方法,没有递归调用。
我们在这篇文章中使用了自下而上的归并排序方法。我们知道合并排序首先合并两个项目,然后是 4 个项目,依此类推。这个想法是使用一个整数变量来存储间隙,以找到需要对链表进行排序的中点。因此,问题简化为合并这里讨论的两个排序的链表。但是,我们不使用附加列表来保留合并列表。相反,我们合并列表本身。间隙在每次迭代中以指数方式增加 2,并重复该过程。
C++
// Iterative C++ program to do merge sort on
// linked list
#include
using namespace std;
/* Structure of the Node */
struct Node {
int data;
struct Node* next;
};
/* Function to calculate length of linked list */
int length(struct Node* current)
{
int count = 0;
while (current != NULL) {
current = current->next;
count++;
}
return count;
}
/* Merge function of Merge Sort to Merge the two sorted parts
of the Linked List. We compare the next value of start1 and
current value of start2 and insert start2 after start1 if
it's smaller than next value of start1. We do this until
start1 or start2 end. If start1 ends, then we assign next
of start1 to start2 because start2 may have some elements
left out which are greater than the last value of start1.
If start2 ends then we assign end2 to end1. This is necessary
because we use end2 in another function (mergeSort function)
to determine the next start1 (i.e) start1 for next
iteration = end2->next */
void merge(struct Node** start1, struct Node** end1,
struct Node** start2, struct Node** end2)
{
// Making sure that first node of second
// list is higher.
struct Node* temp = NULL;
if ((*start1)->data > (*start2)->data) {
swap(*start1, *start2);
swap(*end1, *end2);
}
// Merging remaining nodes
struct Node* astart = *start1, *aend = *end1;
struct Node* bstart = *start2, *bend = *end2;
struct Node* bendnext = (*end2)->next;
while (astart != aend && bstart != bendnext) {
if (astart->next->data > bstart->data) {
temp = bstart->next;
bstart->next = astart->next;
astart->next = bstart;
bstart = temp;
}
astart = astart->next;
}
if (astart == aend)
astart->next = bstart;
else
*end2 = *end1;
}
/* MergeSort of Linked List
The gap is initially 1. It is incremented as
2, 4, 8, .. until it reaches the length of the
linked list. For each gap, the linked list is
sorted around the gap.
The prevend stores the address of the last node after
sorting a part of linked list so that it's next node
can be assigned after sorting the succeeding list.
temp is used to store the next start1 because after
sorting, the last node will be different. So it
is necessary to store the address of start1 before
sorting. We select the start1, end1, start2, end2 for
sorting. start1 - end1 may be considered as a list
and start2 - end2 may be considered as another list
and we are merging these two sorted list in merge
function and assigning the starting address to the
previous end address. */
void mergeSort(struct Node** head)
{
if (*head == NULL)
return;
struct Node* start1 = NULL, *end1 = NULL;
struct Node* start2 = NULL, *end2 = NULL;
struct Node* prevend = NULL;
int len = length(*head);
for (int gap = 1; gap < len; gap = gap*2) {
start1 = *head;
while (start1) {
// If this is first iteration
bool isFirstIter = 0;
if (start1 == *head)
isFirstIter = 1;
// First part for merging
int counter = gap;
end1 = start1;
while (--counter && end1->next)
end1 = end1->next;
// Second part for merging
start2 = end1->next;
if (!start2)
break;
counter = gap;
end2 = start2;
while (--counter && end2->next)
end2 = end2->next;
// To store for next iteration.
Node *temp = end2->next;
// Merging two parts.
merge(&start1, &end1, &start2, &end2);
// Update head for first iteration, else
// append after previous list
if (isFirstIter)
*head = start1;
else
prevend->next = start1;
prevend = end2;
start1 = temp;
}
prevend->next = start1;
}
}
/* Function to print the Linked List */
void print(struct Node** head)
{
if ((*head) == NULL)
return;
struct Node* temp = *head;
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
/* Given a reference (pointer to
pointer) to the head of a list
and an int, push a new node on
the front of the list. */
void push(struct Node** head_ref,
int new_data)
{
struct Node* new_node = new Node;
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
int main()
{
// start with empty list
struct Node* head = NULL;
// create linked list
// 1->2->3->4->5->6->7
push(&head, 7);
push(&head, 6);
push(&head, 5);
push(&head, 4);
push(&head, 3);
push(&head, 2);
push(&head, 1);
mergeSort(&head);
print(&head);
}
Java
// Iterative Java program to do merge sort on
// linked list
class GFG
{
/* Structure of the Node */
static class Node
{
int data;
Node next;
};
/* Function to calculate length of linked list */
static int length(Node current)
{
int count = 0;
while (current != null)
{
current = current.next;
count++;
}
return count;
}
/* Merge function of Merge Sort to Merge the two sorted parts
of the Linked List. We compare the next value of start1 and
current value of start2 and insert start2 after start1 if
it's smaller than next value of start1. We do this until
start1 or start2 end. If start1 ends, then we assign next
of start1 to start2 because start2 may have some elements
left out which are greater than the last value of start1.
If start2 ends then we assign end2 to end1. This is necessary
because we use end2 in another function (mergeSort function)
to determine the next start1 (i.e) start1 for next
iteration = end2.next */
static Node merge(Node start1, Node end1,
Node start2, Node end2)
{
// Making sure that first node of second
// list is higher.
Node temp = null;
if ((start1).data > (start2).data)
{
Node t = start1;
start1 = start2;
start2 = t;
t = end1;
end1 = end2;
end2 = t;
}
// Merging remaining nodes
Node astart = start1, aend = end1;
Node bstart = start2, bend = end2;
Node bendnext = (end2).next;
while (astart != aend && bstart != bendnext)
{
if (astart.next.data > bstart.data)
{
temp = bstart.next;
bstart.next = astart.next;
astart.next = bstart;
bstart = temp;
}
astart = astart.next;
}
if (astart == aend)
astart.next = bstart;
else
end2 = end1;
return start1;
}
/* MergeSort of Linked List
The gap is initially 1. It is incremented as
2, 4, 8, .. until it reaches the length of the
linked list. For each gap, the linked list is
sorted around the gap.
The prevend stores the address of the last node after
sorting a part of linked list so that it's next node
can be assigned after sorting the succeeding list.
temp is used to store the next start1 because after
sorting, the last node will be different. So it
is necessary to store the address of start1 before
sorting. We select the start1, end1, start2, end2 for
sorting. start1 - end1 may be considered as a list
and start2 - end2 may be considered as another list
and we are merging these two sorted list in merge
function and assigning the starting address to the
previous end address. */
static Node mergeSort(Node head)
{
if (head == null)
return head;
Node start1 = null, end1 = null;
Node start2 = null, end2 = null;
Node prevend = null;
int len = length(head);
for (int gap = 1; gap < len; gap = gap*2)
{
start1 = head;
while (start1 != null)
{
// If this is first iteration
boolean isFirstIter = false;
if (start1 == head)
isFirstIter = true;
// First part for merging
int counter = gap;
end1 = start1;
while (--counter > 0 && end1.next != null)
end1 = end1.next;
// Second part for merging
start2 = end1.next;
if (start2 == null)
break;
counter = gap;
end2 = start2;
while (--counter > 0 && end2.next != null)
end2 = end2.next;
// To store for next iteration.
Node temp = end2.next;
// Merging two parts.
merge(start1, end1, start2, end2);
// Update head for first iteration, else
// append after previous list
if (isFirstIter)
head = start1;
else
prevend.next = start1;
prevend = end2;
start1 = temp;
}
prevend.next = start1;
}
return head;
}
/* Function to print the Linked List */
static void print(Node head)
{
if ((head) == null)
return;
Node temp = head;
while (temp != null)
{
System.out.printf("%d ", temp.data);
temp = temp.next;
}
System.out.printf("\n");
}
/* Given a reference (pointer to
pointer) to the head of a list
and an int, push a new node on
the front of the list. */
static Node push( Node head_ref,
int new_data)
{
Node new_node = new Node();
new_node.data = new_data;
new_node.next = (head_ref);
(head_ref) = new_node;
return head_ref;
}
public static void main(String args[])
{
// start with empty list
Node head = null;
// create linked list
// 1.2.3.4.5.6.7
head = push(head, 7);
head = push(head, 6);
head = push(head, 5);
head = push(head, 4);
head = push(head, 3);
head = push(head, 2);
head = push(head, 1);
head = mergeSort(head);
print(head);
}
}
// This code is contributed by Arnab Kundu
Python3
# Iterative Python3 program to do merge sort on
# linked list
''' Structure of the Node '''
class Node:
def __init__(self, data):
self.data = data
self.next = None
''' Function to calculate length of linked list '''
def length(current):
count = 0;
while (current != None):
current = current.next;
count += 1
return count;
''' Merge function of Merge Sort to Merge the two sorted parts
of the Linked List. We compare the next value of start1 and
current value of start2 and insert start2 after start1 if
it's smaller than next value of start1. We do this until
start1 or start2 end. If start1 ends, then we assign next
of start1 to start2 because start2 may have some elements
left out which are greater than the last value of start1.
If start2 ends then we assign end2 to end1. This is necessary
because we use end2 in another function (mergeSort function)
to determine the next start1 (i.e) start1 for next
iteration = end2.next '''
def merge(start1, end1, start2, end2):
# Making sure that first node of second
# list is higher.
temp = None;
if ((start1).data > (start2).data):
start1, start2 = start2, start1
end1,end2 = end2, end1
# Merging remaining nodes
astart = start1
aend = end1;
bstart = start2
bend = end2;
bendnext = (end2).next;
while (astart != aend and bstart != bendnext):
if (astart.next.data > bstart.data):
temp = bstart.next;
bstart.next = astart.next;
astart.next = bstart;
bstart = temp;
astart = astart.next;
if (astart == aend):
astart.next = bstart;
else:
end2 = end1;
''' MergeSort of Linked List
The gap is initially 1. It is incremented as
2, 4, 8, .. until it reaches the length of the
linked list. For each gap, the linked list is
sorted around the gap.
The prevend stores the address of the last node after
sorting a part of linked list so that it's next node
can be assigned after sorting the succeeding list.
temp is used to store the next start1 because after
sorting, the last node will be different. So it
is necessary to store the address of start1 before
sorting. We select the start1, end1, start2, end2 for
sorting. start1 - end1 may be considered as a list
and start2 - end2 may be considered as another list
and we are merging these two sorted list in merge
function and assigning the starting address to the
previous end address. '''
def mergeSort(head):
if (head == None):
return;
start1 = None
end1 = None;
start2 = None
end2 = None;
prevend = None;
len = length(head);
gap = 1
while gap < len:
start1 = head;
while (start1):
# If this is first iteration
isFirstIter = 0;
if (start1 == head):
isFirstIter = 1;
# First part for merging
counter = gap;
end1 = start1;
while (counter != 0 and end1.next):
counter -= 1
end1 = end1.next;
# Second part for merging
start2 = end1.next;
if (not start2):
break;
counter = gap;
end2 = start2;
while (counter != 0 and end2.next):
counter -= 1
end2 = end2.next;
# To store for next iteration.
temp = end2.next;
# Merging two parts.
merge(start1, end1, start2, end2);
# Update head for first iteration, else
# append after previous list
if (isFirstIter):
head = start1;
else:
prevend.next = start1;
prevend = end2;
start1 = temp;
gap = gap*2
prevend.next = start1;
''' Function to print the Linked List '''
def prints(head):
if ((head) == None):
return;
temp = head;
while (temp != None):
print(temp.data, end=' ')
temp = temp.next;
print()
''' Given a reference (pointer to
pointer) to the head of a list
and an int, push a new node on
the front of the list. '''
def push(head_ref, new_data):
new_node = Node(new_data)
new_node.next = (head_ref);
(head_ref) = new_node;
return head_ref
# Driver code
if __name__=='__main__':
# start with empty list
head = None;
# create linked list
# 1.2.3.4.5.6.7
head = push(head, 7);
head = push(head, 6);
head = push(head, 5);
head = push(head, 4);
head = push(head, 3);
head = push(head, 2);
head = push(head, 1);
mergeSort(head);
prints(head);
# This code is contributed by rutvik_56
C#
// Iterative C# program to do merge sort on
// linked list
using System;
class GFG
{
/* Structure of the Node */
public class Node
{
public int data;
public Node next;
};
/* Function to calculate length of linked list */
static int length(Node current)
{
int count = 0;
while (current != null)
{
current = current.next;
count++;
}
return count;
}
/* Merge function of Merge Sort to Merge the two sorted parts
of the Linked List. We compare the next value of start1 and
current value of start2 and insert start2 after start1 if
it's smaller than next value of start1. We do this until
start1 or start2 end. If start1 ends, then we assign next
of start1 to start2 because start2 may have some elements
left out which are greater than the last value of start1.
If start2 ends then we assign end2 to end1. This is necessary
because we use end2 in another function (mergeSort function)
to determine the next start1 (i.e) start1 for next
iteration = end2.next */
static Node merge(Node start1, Node end1,
Node start2, Node end2)
{
// Making sure that first node of second
// list is higher.
Node temp = null;
if ((start1).data > (start2).data)
{
Node t = start1;
start1 = start2;
start2 = t;
t = end1;
end1 = end2;
end2 = t;
}
// Merging remaining nodes
Node astart = start1, aend = end1;
Node bstart = start2, bend = end2;
Node bendnext = (end2).next;
while (astart != aend && bstart != bendnext)
{
if (astart.next.data > bstart.data)
{
temp = bstart.next;
bstart.next = astart.next;
astart.next = bstart;
bstart = temp;
}
astart = astart.next;
}
if (astart == aend)
astart.next = bstart;
else
end2 = end1;
return start1;
}
/* MergeSort of Linked List
The gap is initially 1. It is incremented as
2, 4, 8, .. until it reaches the length of the
linked list. For each gap, the linked list is
sorted around the gap.
The prevend stores the address of the last node after
sorting a part of linked list so that it's next node
can be assigned after sorting the succeeding list.
temp is used to store the next start1 because after
sorting, the last node will be different. So it
is necessary to store the address of start1 before
sorting. We select the start1, end1, start2, end2 for
sorting. start1 - end1 may be considered as a list
and start2 - end2 may be considered as another list
and we are merging these two sorted list in merge
function and assigning the starting address to the
previous end address. */
static Node mergeSort(Node head)
{
if (head == null)
return head;
Node start1 = null, end1 = null;
Node start2 = null, end2 = null;
Node prevend = null;
int len = length(head);
for (int gap = 1; gap < len; gap = gap*2)
{
start1 = head;
while (start1 != null)
{
// If this is first iteration
Boolean isFirstIter = false;
if (start1 == head)
isFirstIter = true;
// First part for merging
int counter = gap;
end1 = start1;
while (--counter > 0 && end1.next != null)
end1 = end1.next;
// Second part for merging
start2 = end1.next;
if (start2 == null)
break;
counter = gap;
end2 = start2;
while (--counter > 0 && end2.next != null)
end2 = end2.next;
// To store for next iteration.
Node temp = end2.next;
// Merging two parts.
merge(start1, end1, start2, end2);
// Update head for first iteration, else
// append after previous list
if (isFirstIter)
head = start1;
else
prevend.next = start1;
prevend = end2;
start1 = temp;
}
prevend.next = start1;
}
return head;
}
/* Function to print the Linked List */
static void print(Node head)
{
if ((head) == null)
return;
Node temp = head;
while (temp != null)
{
Console.Write( temp.data + " ");
temp = temp.next;
}
Console.Write("\n");
}
/* Given a reference (pointer to
pointer) to the head of a list
and an int, push a new node on
the front of the list. */
static Node push( Node head_ref,
int new_data)
{
Node new_node = new Node();
new_node.data = new_data;
new_node.next = (head_ref);
(head_ref) = new_node;
return head_ref;
}
// Driver code
public static void Main(String []args)
{
// start with empty list
Node head = null;
// create linked list
// 1.2.3.4.5.6.7
head = push(head, 7);
head = push(head, 6);
head = push(head, 5);
head = push(head, 4);
head = push(head, 3);
head = push(head, 2);
head = push(head, 1);
head = mergeSort(head);
print(head);
}
}
// This code is contributed by Arnab Kundu
Javascript
输出:
1 2 3 4 5 6 7
时间复杂度: O(n Log n)
辅助空间: O(1)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。