1、归并排序
分治思想:每次从中间分开为两个子问题,对每个子问题排序完成之后,将两个已排序的部分进行归并操作即得到最终排序的结果。
(1)如果数组S中元素个数为0或者1返回
(2)选取中间位置的元素下标,对左半部分SL递归排序,对右半部分SR递归排序
(3)将排好序的SL、SR进行归并后返回最终结果
平均时间复杂度O(NlogN),最坏情况也为O(NlogN),最好情况为O(N)。
C++模版实现:
template <typename T>
void TMergeSort(vector<T> & arr, vector<T> &tmp, int left, int right)
{
if (left < right)
{
int mid = (left + right) / 2;
TMergeSort(arr, tmp, left, mid);
TMergeSort(arr, tmp, mid + 1, right);
int leftPos = left, rightPos = mid + 1, tmpPos = left;
while (leftPos <= mid && rightPos <= right)
if (arr[leftPos] <= arr[rightPos])
tmp[tmpPos++] = arr[leftPos++];
else
tmp[tmpPos++] = arr[rightPos++];
while (leftPos <= mid) tmp[tmpPos++] = arr[leftPos++];
while (rightPos <= right) tmp[tmpPos++] = arr[rightPos++];
for (int i = left; i <= right; i++)
arr[i] = tmp[i];
}
}
2、快速排序
分治思想:分为子问题的时候是随机分,找一个枢轴元素,将此元素的位置找到。随机分的方法也可以使用三数取中值方法,对第一个、最后一个、中间位置元素进行判断,选取大小为中间的元素为枢轴元素,这样可以节约14%左右的比较次数。也可以使用最不安全的分法,就是每次选取第一个元素为枢轴。
(1)如果数组S中元素个数为0或者1,返回
(2)用选定的方法选取一个枢轴元素v
(3)将S-{v}划分为两个不相交的集合,其中S+ = {x | x >= v},S- = {x | x <= v}
(4)对S+和S- 分别进行递归排序,S- 、v、S+即为排序的最终结果
平均时间复杂度为O(NlogN),最坏情况为O(N^2),最好情况为O(NlogN)。
C++模版实现如下:
template <typename T>
void TQuickSort(vector<T> & p, int low, int high)
{
if (low < high)
{
int l = low, h = high, m = (low + high) / 2, p_index;
//三数取中值方法选择枢轴
T pivot;
if ((p[l] <= p[m] && p[m] <= p[h]) || (p[h] <= p[m] && p[m] <= p[l]))
{
pivot = p[m];
p_index = m;
}
if ((p[l] <= p[h] && p[h] <= p[m]) || (p[m] <= p[h] && p[h] <= p[l]))
{
pivot = p[h];
p_index = h;
}
if ((p[m] <= p[l] && p[l] <= p[h]) || (p[h] <= p[l] && p[l] <= p[m]))
{
pivot = p[l];
p_index = l;
}
while(l < h)
{
while (l < h && p[h] >= pivot) h--;
p[p_index] = p[h]; p_index = h;
while (l < h && p[l] < pivot) l++;
p[p_index] = p[l]; p_index = l;
}
p[p_index] = pivot;
TQuickSort(p, low, p_index);
TQuickSort(p, p_index + 1, high);
}
}