一,准备子函数
1,cut函数
将链表切成两半,返回中间节点。
使用快慢指针。
Node* cut(Node* head)
{
Node* fast, * slow, * second_head;
fast = slow = head;
while (fast && fast->next)
{
fast = fast->next;
if (fast->next)
{
fast = fast->next;
slow = slow->next;
}
}
second_head = slow->next;
slow->next = NULL;
return second_head;
}
为了严谨,要检查head是否为空,因为后面有slow->next,如果slow为空,就会报错。
图片解释为什么可以让慢指针总是在while结束后指向n处节点。
2,mergesort函数,排序的主体函数
void emergesort(Node*& head)
{
if (head->next)//单个节点是基准情况,就直接结束了。
{
Node* second_head = cut(head);
emergesort(head);
emergesort(second_head);
//先将左右两边的链表排好序,然后再将其合并。
emerge(head, second_head);
}
}
3,merge函数,合并两个有序链表
Node* merge(Node*& head1, Node*& head2)
{
Node* cur1, * cur2, * cur;
Node temp(-1);
cur1 = head1;
cur2 = head2;
cur = &temp;
//通过设置变量temp,避免了特殊处理头节点。
while (cur1 && cur2)
{
if (cur1->value < cur2->value)
{
cur->next = cur1;
cur = cur->next;
cur1 = cur1->next;
}
else
{
cur->next = cur2;
cur = cur->next;
cur2 = cur2->next;
}
}
if (cur1) cur->next = cur1;
else cur->next = cur2;
return temp.next;
}
注意点是merge和mergesort都是引用传递,因为mergesort不返回节点指针,我要始终保证参入的head节点在排序后仍是head。
二,主函数部分
#include<iostream>
#include"listndoe.h"
using namespace std;
int main()
{
int arr[] = {1,3,5,7,10,2,4,6,8};
int len = sizeof(arr) / sizeof(int);
Node* head = create_list(arr, len);
print_list(head);
mergesort(head);
print_list(head);
return 0;
}