常见的排序算法 - 归并排序

归并排序是一种分治思想的排序算法。它将一个数组分成两个子数组,分别对这两个子数组进行排序,然后将排序好的两个子数组归并在一起,得到最终的有序数组。归并排序是一种稳定的排序算法。

归并排序的流程如下:

1将整个数组分成两个子数组。
2递归地对左边的子数组进行归并排序,递归地对右边的子数组进行归并排序。
3将已经排序好的两个子数组合并成一个最终的有序数组。

c语言实现如下:

void merge_sort(int arr[], int left, int right) {
    
    
    if (left < right) {
    
    
        int middle = (left + right) / 2;
        merge_sort(arr, left, middle);
        merge_sort(arr, middle + 1, right);
        merge(arr, left, middle, right);
    }
}

void merge(int arr[], int left, int middle, int right) {
    
    
    int i, j, k;
    int n1 = middle - left + 1;
    int n2 =  right - middle;
    int L[n1], R[n2];

    for (i = 0; i < n1; i++)
        L[i] = arr[left + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[middle + 1+ j];

    i = 0;
    j = 0;
    k = left;
    while (i < n1 && j < n2) {
    
    
        if (L[i] <= R[j]) {
    
    
            arr[k] = L[i];
            i++;
        }
        else {
    
    
            arr[k] = R[j];
            j++;
        }
        k++;
    }

    while (i < n1) {
    
    
        arr[k] = L[i];
        i++;
        k++;
    }

    while (j < n2) {
    
    
        arr[k] = R[j];
        j++;
        k++;
    }
}

归并排序的优点是它能保证排序数组的稳定性,即相同的元素排序前后的相对位置不会改变,而且它的时间复杂度是O(nlogn),在大部分情况下都能得到较好的性能。

但是归并排序的空间复杂度是O(n),如果数据量比较大,可能会占用较多的空间,所以归并排序不适用于数据量特别大的场景。

代码也可以进行简化:

void merge_sort(int q[], int l, int r)
{
    
    
    if (l >= r) return;

    int mid = l + r >> 1;
    merge_sort(q, l, mid);
    merge_sort(q, mid + 1, r);

    // 归并的过程
    int k = 0, i = l, j = mid + 1;
    while (i <= mid && j <= r)
        if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
        else tmp[k ++ ] = q[j ++ ];

    // 扫尾
    while (i <= mid) tmp[k ++ ] = q[i ++ ];
    while (j <= r) tmp[k ++ ] = q[j ++ ];

    // 物归原主
    for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];  // i循环的是原数组,j循环的是临时数组。
}

归并排序是稳定的,而且时间复杂度是O(nlogn),空间复杂度是O(n),如果需要排序的数据量不是特别大,并且要求排序稳定性的话,归并排序是一个不错的选择。

猜你喜欢

转载自blog.csdn.net/sorcererr/article/details/128700614
今日推荐