2.认识 O(N*logN) 的排序
第一节、master 公式
在编程中,递归是非常常见的一种算法,由于代码简洁而应用广泛,但递归相比顺序执行或循环程序,时间复杂度难以计算,而master公式就是用于计算递归程序的时间复杂度。
T(N) = a*T(N/b) + O(N^d);
下面对参数进行解释:
- b:子过程的样本量
- a:子过程的计算次数
- O(N^d):子结果合并的时间复杂度
满足如上公式的程序都可以根据master公式计算时间复杂度:
- log(b,a) > d :时间复杂度为O(N^log(b,a))
- log(b,a) = d :时间复杂度为O(N^d * logN)
- log(b,a) < d :时间复杂度为O(N^d)
第二节、求中值
在学习归并排序之前,我们先学习一个简单的算法:当我们求一个值的中值时,可以使用:
int mid = L + ((R - L) >> 1);
这样可以避免内存泄露。
第三节、归并排序
归并排序:归并排序也是将速度分别有序化的过程,先解释合并的部分。我们假设有两个有序的数组。我们将这两个数组进行合并。使用一个临时的数组。当这两个数组都没有达到边界时。对对应元素进行比较。叫小的数放进临时数组中。如果相等,则左边的数组先放入。放入一个之后,对应的只增加1。
我们将一个数组划为两部分。然后递归调用这个marge函数,就可以进行归并排序。
根据 master 公式计算,归并排序的master 公式为:
T(N) = 2*T(N/2) + O(N^1);
log(2,2) = 2;
时间复杂度为O(N^d * logN)。
因为归并排序没有浪费比较操作,每一次的比较行为都成为了一个有序的部分。
下面给出代码:
#include <iostream>
#include <vector>
using namespace std;
#pragma once
class MargeSort
{
public:
static void sort(vector<int>& arr);
static void progress(vector<int>&, int left, int right);
static void marge(vector<int>&, int left, int right, int mid);
private:
};
#include "MargeSort.h"
void MargeSort::sort(vector<int>& arr)
{
int length = arr.size();
if (length < 2) return;
progress(arr, 0, length - 1);
}
void MargeSort::progress(vector<int>& arr, int left, int right)
{
if (left == right