前言:
前面三篇文章分别介绍了三种排序算法:冒泡排序、插入排序和选择排序。它们的实现思想都是基于排序问题本身产生的,时间复杂度都是θ(n^2)。
而现在介绍的两种排序算法:归并排序和快速排序,它们的思想除了对于排序本身外,还可以进一步抽象为:分治思想
一、分治思想
分治思想,顾名思义就是将一个大而复杂的问题分解为若干个性质相同且相互独立 的小问题分别求解,然后找到合适的组合方法将若干小问题的解组合生成原问题的解。
如果第一遍分解得到的若干问题仍然很复杂,则可以继续分解直至可以求解为止。下面我们就从分治思想的角度介绍归并排序和快速排序。
二、归并排序
- 基本思想:有点“分解并征服/Divide and Conquer”的意思,具体步骤如下:
(1)将一个序列分成两个子序列,并排序两个子序列
(2)重新组合两个子序列使成为一个有序的序列
(3)下图可以形象的展示分解及组合的过程(来源于百度百科):
- 代码实现(C++):
void mergeTwoArray(int arrayName[], int p, int q, int r);
//to merge arrayName[p...q] and arrayName[q+1...r], both in ascending order
void mergeSort(int arrayName[], int low, int high);
//to sort "arrayName" between low and high
void mergeTwoArray(int arrayName[], int p, int q, int r)
{
int assistArray[1000];
int s = p;
int t = q + 1;
//initialize two indicators to point at the beginning of two arrays
int k = p;
while ((s <= q) && (t <= r))
{
if (arrayName[s] <= arrayName[t])
{
assistArray[k] = arrayName[s];
s += 1;
}
else
{
assistArray[k] = arrayName[t];
t += 1;
}
k += 1;
}
if (s == q + 1)
for (k, t;k <= r;k++, t++)
assistArray[k] = arrayName[t];
else
for (k, s;k <= r;k++, s++)
assistArray[k] = arrayName[s];
for (p;p <= r;p++)
arrayName[p] = assistArray[p];
}
void mergeSort(int arrayName[], int low, int high)
{
int mid = 0;
if (low < high)
{
mid = (low + high) / 2;
mergeSort(arrayName, low, mid);
mergeSort(arrayName, mid + 1, high);
mergeTwoArray(arrayName, low, mid, high);
}
}
3.时间复杂度为θ(nlogn):
三、快速排序
- 基本思想:将一个序列分解成两个子序列,其中一个子序列的元素比另外一个子序列的元素都要小。为了完成这种目标,我们可以在一个待分解的序列中找到一个参考点(称之为支点,pivot)。下图是一个例子:
- 代码实现(C++)
void swapValues(int arrayName[], int i, int j);
//swap the values of arrayName[i] and arrayName[j]
int splitArray(int arrayName[], int low, int high);
//to split an array between low and high and return the new position of the pivot
void quickSort(int arrayName[], int low, int high);
//to sort "arrayName" between low and high
void swapValues(int arrayName[], int i, int j)
{
int middleVariable = 0;
middleVariable = arrayName[i];
arrayName[i] = arrayName[j];
arrayName[j] = middleVariable;
}
int splitArray(int arrayName[], int low, int high)
{
int i = low;
int x = arrayName[low];
for (int j = low + 1;j <= high;j++)
if (arrayName[j] <= x)
{
i += 1;
if (i != j)
swapValues(arrayName, i, j);
}
swapValues(arrayName, low, i);
return i;
}
void quickSort(int arrayName[], int low, int high)
{
if (low < high)
{
int w = splitArray(arrayName, low, high);
//"w" represents the new position of the pivot in a spliting
quickSort(arrayName, low, w - 1);
quickSort(arrayName, w + 1, high);
}
}
3.时间复杂度:θ(nlogn)。
算法包
点击这里下载排序算法源代码,包括:插入排序、选择排序、冒泡排序、快速排序、归并排序、0交换排序等多种算法,以整数序列为例实现。