1、归并排序(Merge Sort)
归并排序的性能不受输入数据的影响,始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间。
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
1.1 算法描述
- 把长度为n的输入序列分成两个长度为n/2的子序列;
- 对这两个子序列分别采用归并排序;
- 将两个排序好的子序列合并成一个最终的排序序列。
1.2 C++代码(数组):
#include <iostream>
#include <vector>
using namespace std;
void merge(int nums[], int left, int mid, int right)
{
int length1 = mid - left + 1;
int length2 = right - mid;
int* len1 = new int[length1+1];
int* len2 = new int[length2+1];
int i, j, k;
for (i = 0; i < length1; i++) len1[i] = nums[left + i];
for (j = 0; j < length2; j++) len2[j] = nums[mid + j + 1];
len1[length1] = INT_MAX;
len2[length2] = INT_MAX;
for (i = 0, j = 0, k = left; k <= right; k++)
{
if (len1[i] <= len2[j])
nums[k] = len1[i++];
else
nums[k] = len2[j++];
}
delete []len1;
delete []len2;
}
void mergeSort(int nums[], int left, int right)
{
if (left < right)
{
int mid = (left + right) / 2;
mergeSort(nums, left, mid);
mergeSort(nums, mid + 1, right);
merge(nums, left, mid, right);
}
}
int main()
{
int nums[] = { 7, 5, 3, 1, 8, 6, 4, 2 };
int length = sizeof(nums) / sizeof(int);
mergeSort(nums, 0, length - 1);
for (int v : nums)
cout << v << " ";
return 0;
}
2. C++代码(链表):
// 合并两个有序的链表
ListNode* merge(ListNode* head1, ListNode* head2)
{
ListNode guard_node(0);
ListNode* mList = &guard_node;
while (head1 && head2)
{
if (head1->val <= head2->val)
{
mList->next = head1;
head1 = head1->next;
}
else
{
mList->next = head2;
head2 = head2->next;
}
mList = mList->next;
}
if (head1)
mList->next = head1;
if (head2)
mList->next = head2;
return guard_node.next;
}
// 链表实现归并排序
ListNode* sortList(ListNode* head)
{
if (head == NULL || head->next == NULL) return head;
ListNode* fast = head;
ListNode* slow = head;
while (fast->next && fast->next->next)
{
slow = slow->next;
fast = fast->next->next;
}
ListNode* head2 = slow->next;
slow->next = NULL;
ListNode* head1 = head;
head1 = sortList(head);
head2 = sortList(head2);
return merge(head1, head2);
}