148. 排序链表

题目:
在这里插入图片描述

思路:
首先这题是归并排序的思想,

归并排序代码:

void Merge(vector<int> &arr, int start, int end,int mid, vector<int> &temparr)
{
	int i_start = start;
	int i_end = mid;
	int j_start = mid + 1;
	int j_end = end;

	int length = 0;
	//合并两个有序序列(为什么就有序了)  思考!!!
	while (i_start<= i_end&& j_start<= j_end)//两个有序数组合并后可能会有个对于的 
	{
		if (arr[i_start]< arr[j_start])
		{
			temparr[length] = arr[i_start];
			length++;
			i_start++;
		}
		else
		{
			temparr[length] = arr[j_start];
			length++;
			j_start++;
		}
	}

	while (i_start<= i_end)//这是判断的
	{
		temparr[length] = arr[i_start];
		length++;
		i_start++;
	}

	while (j_start <= j_end)
	{
		temparr[length] = arr[j_start];
		length++;
		j_start++;
	}

	//辅助空间数据覆盖到原空间
	for (int i=0;i<length;i++)
	{
		arr[start+i]=temparr[i];

	}

}


void MergeSort(vector<int> &arr, int start, int end, vector<int> &temparr)
{
	

	if (start>=end)
	{
		return;
	}
	//划分到最后是每一个里面只有一个数据 
	int mid = (start + end) / 2;
	MergeSort(arr,start,mid, temparr);
	MergeSort(arr, mid+1, end, temparr);

	Merge(arr, start, end, mid, temparr);
}

	

模仿数组中的两两归并,单链表排序也就是说我们需要进行每次划分,这个相当于归并排序代码中的(left+right)/2 ,然后到达某个不能再划分的条件下面的时候再进行两两归并。也就是merge函数

这题我们需要注意的是
1.不能再划分的状态,在数组中是start>=end,单链表中呢?

我们需要知道在数组vector中start>=end 不能改为start>end 不然会在sort中造成死循环。

单链表中终止条件是 head == nullptr 与 head->next == nullptr先后循序是不能交换的

if (head == nullptr || head->next == nullptr) return head;

2.数组中vector中进行归并排序过程中有mid,单链表中的mid又是如何表示的?
我们首先需要知道vector中mid是为了将数组的vector分成两个部分
因此我们只需要将链表分成两个部分就可以了

分成两个链表就是说
有两种写法
方法一:

	ListNode* slow = head;
		ListNode* fast = head->next;
		
		while (fast!= nullptr&&fast->next!= nullptr)
		{
			slow = slow->next;
			fast = fast->next->next;
		}

		ListNode* rightHead = slow->next;
		slow->next = nullptr;

方法二:

		ListNode* slow = head;
		ListNode* fast = head;
		ListNode* pre = head;
		while (fast != nullptr&&fast->next != nullptr)//中间分开
		{
			pre = slow;
			slow = slow->next;
			fast = fast->next->next;
		}

		//将原本的整个单链表分成两个单链表(分)
		ListNode* rightHead = slow;
		pre->next = nullptr;

3.数组中sort和merge是没有返回值的,但是单链表中不支持随机访问,因此是需要返回值的
我们通过第二个问题就可以知道了,返回值就是每次划分链表的头结点

代码:

#include<iostream>
using namespace std;
 // Definition for singly-linked list.
  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* sortList(ListNode* head)
	{
		if (head == nullptr || head->next == nullptr) return head;

		//ListNode* slow = head;
		//ListNode* fast = head;
		//ListNode* pre = head;
		//while (fast != nullptr&&fast->next != nullptr)//中间分开
		//{
		//	pre = slow;
		//	slow = slow->next;
		//	fast = fast->next->next;
		//}

		将原本的整个单链表分成两个单链表(分)
		//ListNode* rightHead = slow;
		//pre->next = nullptr;

		ListNode* slow = head;
		ListNode* fast = head->next;
		
		while (fast!= nullptr&&fast->next!= nullptr)
		{
			slow = slow->next;
			fast = fast->next->next;
		}

		ListNode* rightHead = slow->next;
		slow->next = nullptr;

		ListNode* leftList = sortList(head);

		ListNode* rightList = sortList(rightHead);

		return merge(leftList, rightList);//merge的含义是并

	}

	ListNode*  merge(ListNode* leftList, ListNode* rightList)
	{
		ListNode node(-1);
		ListNode * dummpy = &node;
		ListNode *tail = dummpy;

		while (leftList != nullptr&&rightList != nullptr)
		{
			if (leftList->val > rightList->val)
			{
				tail->next = leftList;

				tail = leftList;
				leftList = leftList->next;
			}
			else
			{
				tail->next = rightList;

				tail = rightList;
				rightList = rightList->next;
			}
		}

		if (leftList != nullptr)
		{
			tail->next = leftList;
		}

		if (rightList!=nullptr)
		{
			tail->next = rightList;
		}

		return dummpy->next;
	}
};
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值