数据结构双向链表的归并排序 | 第五套

638 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

给定一个双向链表,编写一个函数,使用归并排序以递增的顺序对双向链表进行排序。
比如下面的双链表应该改成24810

image.png

单链表的归并排序已经讨论过了。这里的重要变化是在合并两个列表时也要修改前面的指针。

下面是双向链表归并排序的实现。

#include <bits/stdc++.h>
using namespace std;
class Node
{
	public:
	int data;
	Node *next, *prev;
};

Node *split(Node *head);

合并两个链表的函数

Node *merge(Node *first, Node *second)
{
	// 如果第一个链表为空
	if (!first)
		return second;

	// 如果第二个链表为空
	if (!second)
		return first;

	// 选择较小的值
	if (first->data < second->data)
	{
		first->next = merge(first->next,second);
		first->next->prev = first;
		first->prev = NULL;
		return first;
	}
	else
	{
		second->next = merge(first,second->next);
		second->next->prev = second;
		second->prev = NULL;
		return second;
	}
}

执行归并排序的函数

Node *mergeSort(Node *head)
{
	if (!head || !head->next)
		return head;
	Node *second = split(head);

	// 重复左半部分和右半部分
	head = mergeSort(head);
	second = mergeSort(second);

	// 合并已排序的两半
	return merge(head,second);
}

在双向链表的开头插入新节点的实用函数

void insert(Node **head, int data)
{
	Node *temp = new Node();
	temp->data = data;
	temp->next = temp->prev = NULL;
	if (!(*head))
		(*head) = temp;
	else
	{
		temp->next = *head;
		(*head)->prev = temp;
		(*head) = temp;
	}
}

在向前和向后两个方向打印双向链表的实用函数

void print(Node *head)
{
	Node *temp = head;
	cout<<"使用下一个指针进行前向遍历\n";
	while (head)
	{
		cout << head->data << " ";
		temp = head;
		head = head->next;
	}
	cout << "\n使用 prev 指针向后遍历\n";
	while (temp)
	{
		cout << temp->data << " ";
		temp = temp->prev;
	}
}

交换两个整数的实用函数

void swap(int *A, int *B)
{
	int temp = *A;
	*A = *B;
	*B = temp;
}

将一个双向链表 (DLL) 拆分为 2 个半大小的 DLL

Node *split(Node *head)
{
	Node *fast = head,*slow = head;
	while (fast->next && fast->next->next)
	{
		fast = fast->next->next;
		slow = slow->next;
	}
	Node *temp = slow->next;
	slow->next = NULL;
	return temp;
}

驱动程序

int main(void)
{
	Node *head = NULL;
	insert(&head, 5);
	insert(&head, 20);
	insert(&head, 4);
	insert(&head, 3);
	insert(&head, 30);
	insert(&head, 10);
	head = mergeSort(head);
	cout << "排序后的链表\n";
	print(head);
	return 0;
}

输出: 

排序后的链表
使用下一个指针进行前向遍历
3 4 5 10 20 30
使用 prev 指针向后遍历
30 20 10 5 4 3