第二章 算法基础

插入排序

插入排序的工作方式像许多人排列一手扑克牌。开始时,我们的左手为空且桌子上的牌面向下。然后,我们每次从桌子上拿走一张牌并将它插入左手中的正确位置。为了找到一张牌的正确位置,我们从右到左将它与已经在手上的每张牌进行比较,如图所示。

 代码实现

template<class T>
void InsertionSort(T a[], int nums) {
    for (int i = 1; i < nums; i++) {
        T key = a[i];
        int j = i - 1;
        while (j >= 0 && a[j] > key) {
            a[j + 1] = a[j];
            j--;
        }
        a[j + 1] = key;
    }
}

分治法

许多有用的算法在结构上是递归的:为了解决一个给定的问题,算法一次或多次递归地调用其自身以解决紧密相关的若干子问题。这些算法典型地遵循分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后再结合这些子问题的解建立原问题的解。

分治模式在每层递归时都有三个步骤

  • 分解原问题为若干子问题,这些子问题是原问题的规模较小的实例。
  • 解决这些子问题,递归地求解各子问题。然后,若子问题的规模足够小,则直接求解。
  • 合并这些子问题的解成原问题的解。

归并排序算法完全遵循分治模式。直观上其操作如下:

  • 分解:将待排序的具有 n 个元素的序列分解成各具 n/2 个元素的两个子序列。
  • 解决:使用归并排序递归地排列两个子序列。
  • 合并:合并两个已排序的子序列。

当待排序的序列长度为 1 时,递归“开始回升”,在这种情况下不做任何工作,因为长度为 1 的每个序列都已排好序。

代码实现

template<class T>
void Merge(T a[], int p, int q, int r) {
    int n1 = q - p + 1, n2 = r - q;
    T *left = new T[n1 + 1], *right = new T[n2 + 1];
for (int i = 0; i < n1; i++) { left[i] = a[p + i]; } left[n1] = max; for (int i = 0; i < n2; i++) { right[i] = a[q + i + 1]; } right[n2] = max;
int i = 0, j = 0; for (int k = p; k <= r; k++) { if (left[i] < right[j]) { a[k] = left[i]; i++; } else { a[k] = right[j]; j++; } } }
template
<class T> void MergeSort(T a[], int p, int r) { if (p < r) { int q = (p + r) / 2; MergeSort(a, p, q); MergeSort(a, q + 1, r); Merge(a, p, q, r); } }

猜你喜欢

转载自www.cnblogs.com/bjxqmy/p/12498525.html