分别使用快排和归并排序对链表进行排序

题目描述:
在这里插入图片描述
因为要求时间复杂度为O(nlogn),而时间复杂度为O(nlogn)的排序算法有快排,归并排序和堆排。

那么首先,链表的相关操作如下:

struct LinkNode {
	int data;
	struct LinkNode* next;
	LinkNode() : next(nullptr) {}  //带有表头结点
	LinkNode(int d) : data(d), next(nullptr) {}
};

void addNode(LinkNode* head, int data) {
	LinkNode* p = head;
	while (p->next) p = p->next;
	LinkNode* q = new LinkNode(data);
	p->next = q;
}

void deleteNode(LinkNode* head) {
	while (head) {
		LinkNode* p = head;
		head = head->next;
		delete(p);
	}
}

快排

快排的思想是每次选取一个元素作为基准元素,由于链表的特性,因此我们直接选择第一个结点的值即可,同时我们只能依次顺序遍历,而不是像数组那样前后两个指针同时遍历,示意图如下:

在这里插入图片描述
代码实现如下:

LinkNode* partition(LinkNode* low, LinkNode* high) {
	if (low == high || low->next == high) return low;
	int key = low->data;  //选择low作为基准元素
	LinkNode* p = low, * q = low;
	while (q != high) {  //从low开始向后进行一次遍历
		if (q->data < key) {
			p = p->next;
			swap(p->data, q->data);
		}
		q = q->next;
	}
	swap(low->data, p->data);
	return p;
}

void quick_sort(LinkNode* low, LinkNode* high) {
	if (low == high || low->next == high) return;
	LinkNode* mid = partition(low, high);
	quick_sort(low, mid);
	quick_sort(mid->next, high);
}

LinkNode* quickSort(LinkNode* head) {
	if (head == nullptr || head->next == nullptr) return head;
	quick_sort(head->next, nullptr);
	return head;
}

归并排序

归并排序需要先从中间断开,然后再合并,因此断开的过程可以使用快慢两指针:

LinkNode* getMid(LinkNode* head) {  //获取中间节点并分段
	LinkNode* fast = head;
	LinkNode* slow = head;
	LinkNode* prev = head;
	while (true) {
		if (fast == nullptr) break;
		fast = fast->next;
		if (fast == nullptr) break;
		fast = fast->next;

		prev = slow;
		slow = slow->next;
	}
	prev->next = nullptr;  //将链表分为两段
	return slow;
}

LinkNode* merge(LinkNode* head1, LinkNode* head2) {
	LinkNode* head = new LinkNode();
	LinkNode* tail = head;
	while (head1 && head2) {
		LinkNode* p;
		if (head1->data < head2->data) {
			p = head1;
			head1 = head1->next;
		}
		else {
			p = head2;
			head2 = head2->next;
		}
		p->next = tail->next;
		tail->next = p;
		tail = tail->next;
	}
	if (head1) tail->next = head1;
	if (head2) tail->next = head2;
	return head->next;
}

LinkNode* mergeSort(LinkNode* head) {
	if (head == nullptr || head->next == nullptr) return head;
	LinkNode* head1 = head;
	LinkNode* head2 = getMid(head);  //获取中间节点,将链表分为两段
	head1 = mergeSort(head1);  //分别对两段链表进行排序
	head2 = mergeSort(head2);
	return merge(head1, head2);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花无凋零之时

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值