归并排序 之 单向链表

归并排序----单向链表

1:单向链表快速寻找中间结点

快慢指针:慢指针走一步,快指针走两步
	// 精彩代码--快慢指针寻找列表 中点
	// 快慢指针寻找列表 的中点
	ListNode* findMid(ListNode* head, ListNode* tail) {   // [head, tail);  tail  ==  nullptr
		ListNode* fast;
		ListNode* slow;
		slow = head;
		fast = head->next;
		if (fast->next == nullptr) {
			return slow;
		}
		while (fast != tail) {
			slow = slow->next;
			fast = fast->next;
			if (fast != tail) {
				fast = fast->next;
			}
		}
		return slow;
	}

2:哨兵结点的引入

指向第一个结点,方便将结点插入到头节点的前面

	ListNode* merge(ListNode* head1, ListNode* head2) {
		// head2 -->  head1 中
		// 一个形式头结点
		// 在 head1 所指向的 链表之前创建出一个 形式头节点
		// 为了以后插入元素方便
		ListNode* hot = new ListNode(-1);
		hot->next = head1;

		ListNode* ptr1 = head1;
		ListNode* ptr2 = head2;
		ListNode* tmp = hot;  // hot 出现的很少,但很关键
		// 短的链表插入到长的链表中去
		while (ptr1 != nullptr && ptr2 != nullptr) {
			if (ptr1->val <= ptr2->val) {
				tmp = tmp->next; // 空结点的前一个结点
				ptr1 = ptr1->next;
			} else {
				tmp = insert_one(tmp, ptr2->val);
				ptr2 = ptr2->next;
			}
		}
		// 第二条链表中还有元素没有插入完的话
		while (ptr2 != nullptr) {
			tmp = insert_one(tmp, ptr2->val);
			ptr2 = ptr2->next;
		}
		return hot->next;
	}

归并排序—单向链表排序 完整版代码

#include <iostream>
using namespace std;
struct ListNode {
	int val;
	ListNode* next;
	ListNode() : val(0), next(nullptr) {}
	ListNode(int x) : val(x), next(nullptr) {}
	ListNode(int x, ListNode* next) : val(x), next(next) {}
};
class Solution {
public:
	// 快慢指针寻找列表 的中点
	ListNode* findMid(ListNode* head, ListNode* tail) {   // [head, tail);  tail  ==  nullptr
		ListNode* fast;
		ListNode* slow;
		slow = head;
		fast = head->next;
		if (fast->next == nullptr) {
			return slow;
		}
		while (fast != tail) {
			slow = slow->next;
			fast = fast->next;
			if (fast != tail) {
				fast = fast->next;
			}
		}
		return slow;
	}
	// 插入到 head1 的后面
	ListNode* insert_one(ListNode* head1, int val) {
		if (head1 == nullptr) {
			return nullptr;
		}
		ListNode* tmp = nullptr;
		tmp = new ListNode(val);
		tmp->next = head1->next;
		head1->next = tmp;
		return tmp; // 返回指向新结点的指针
	}
	// 合并有序单链表
	// head1 可以和空 链表合并, head1 || head2 为空,merge 都能很好的完成工作
	ListNode* merge(ListNode* head1, ListNode* head2) {
		// head2 -->  head1 中
		// 一个形式头结点
		// 在 head1 所指向的 链表之前创建出一个 形式头节点
		// 为了以后插入元素方便
		ListNode* hot = new ListNode(-1);
		hot->next = head1;

		ListNode* ptr1 = head1;
		ListNode* ptr2 = head2;
		ListNode* tmp = hot;  // hot 出现的很少,但很关键
		// 短的链表插入到长的链表中去
		while (ptr1 != nullptr && ptr2 != nullptr) {
			if (ptr1->val <= ptr2->val) {
				tmp = tmp->next; // 空结点的前一个结点
				ptr1 = ptr1->next;
			} else {
				tmp = insert_one(tmp, ptr2->val);
				ptr2 = ptr2->next;
			}
		}
		// 第二条链表中还有元素没有插入完的话
		while (ptr2 != nullptr) {
			tmp = insert_one(tmp, ptr2->val);
			ptr2 = ptr2->next;
		}
		return hot->next;
	}
	void mergeSort(ListNode* &head, ListNode* tail) {
		
		if (head == nullptr || head->next == nullptr) {
			return;
		}
		ListNode* tmp = findMid(head, tail);
		ListNode* tmp2 = tmp->next;
		tmp->next = nullptr;
		mergeSort(head, tmp->next); // [head, ]
		mergeSort(tmp2, tail); // [tmp2, tail)
		head = merge(head, tmp2);
	}

	ListNode* sortList(ListNode* head) {
		if (head == nullptr) {
			return head;
		}
		mergeSort(head, nullptr);
		return head;
	}
	void display(ListNode* ptr) {
		while (ptr != nullptr) {
			cout << ptr->val << " ";
			ptr = ptr->next;
		}
		cout << endl;
	}
};
int main() {
	Solution lt;

	ListNode n1(5);
	ListNode n2(2);
	

	//ListNode n3(1);

	n1.next = &n2;
	//n2.next = &n3;
	//n3.next = &n4;



	lt.display(lt.sortList(&n1));



	return 0;
}



































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值