当前位置:   article > 正文

归并排序算法详解及示例_归并排序伪代码

归并排序伪代码

归并排序

归并排序算法是在分治算法的基础上设计出来的一种排序算法,它可以可以对指定的序列完成升序,(由小到大),或降序(由大到小),时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

实现排序的思路

1.将整个待排序划分成多个不可再分的待排序序列,每个子序列中仅有一个元素;
2.所有的子序列进行两两合并,合并过程中完成排序操作,最终合并得到的新序列,就是排序序列。

示例

使用归并排序算法对{7,6,8,9,3,4,1,0},实现升序排序的过程。
1.将{7,6,8,9,3,4,1,0}分割成多个子序列,每个子序列中仅包含一个元素,分割过程如下:
在这里插入图片描述
图1 归并排序算法分割序列的过程
2.将最终分割的序列两两合并,重新整合为一个有序序列,合并的过程如下所示:
在这里插入图片描述
图2 归并排序算法整合所有子序列的过程。

伪代码

归并排序算法可以借助递归的思想实现:

对应的伪代码如下:
输入arr[n]   //输入要排序的序列
merge_sort(arr[n], p, q){ //对[p,q]区域大的元素进行归并排序
	if p < q;             //对[p,q]区域不断采用对半分割的方式,最终将整个区域划分为多个仅包含1个元素(p==q)的序列
	mid = (p+q)/2;
	merge_sort(arr[n],p,mid);
	merge_sort(arr[n],mid+1,q);
	merge(arr,p,mid,q);            //调用实现归并过程的代码模块。
}
merge_sort() 用于将整个序列分割成多个子序列,merge() 用来合并这些子序列,合并的实现方式为:
1.[p, mid][mid+1, q] 两个区域的元素分别拷贝到 leftarr 和 rightarr 区域。
2.从 leftarr 和 rightarr 区域中各个取出第一个元素,比较它们的大小;
3.将较小的元素拷贝到 [p, q] 区域,然后从较小元素所在的区域内取出下一个元素,继续进行比较;
4.重复执行第 3 步,直至 leftarr 和 rightarr 内的元素全部拷贝到 [p, q] 为止。
  如果 leftarr 或者 rightarr 有一方为空,则直接将另一方的所有元素依次拷贝到 [p, q] 区域。
对应的伪代码如下:
merge(arr[n] , p , mid , q):                          // 该算法表示将 [p , mid] 和 [mid+1 , q] 做归并操作
    leftnum <- mid - p + 1                            // 统计 [p , mid] 区域内的元素个数
    rightnum <- q - mid                               // 统计 [mid+1 , q] 区域内的元素个数
    leftarr[leftnum] <- arr[p ... mid]                // 分别将两个区域内的元素各自拷贝到另外两个数组中
    rightarr[rightnum] <- arr[mid+1 ... q]
    i <- 1 , j <- 1
    for k <- p to q :             // 从 leftarr 和 rightarr 数组中第 1 个元素开始,比较它们的大小,将较小的元素拷贝到 arr 数组的 [p , q] 区域
        if leftarr[i] ≤ rightarr[j] :
            arr[k] = leftarr[i]
            i <- i+1
        else :
            arr[k] = right[j]
            j <- j+1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

结合伪代码,如下是用归并排序算法对 {7,6,8,9,3,4,1,0} 进行升序排序的 C 语言程序:

#include <stdio.h>
//实现分割操作的函数
void merge_sort(int* arr, int p, int q);
//实现归并操作的函数
void merge(int* arr, int p, int mid, int q);
int main() {
    int i = 0;
    int arr[8] = { 7,6,8,9,3,4,1,0 };
    //对 arr 数组中第 1 至 8 个元素进行归并排序
    merge_sort(arr, 1, 8);
    while (i < 8)
    {
        printf("%d ", arr[i]);
        i++;
    }
    return 0;
}
//实现分割操作的函数,[p,q] 用于指定归并排序的区域范围,
void merge_sort(int* arr, int p, int q) {
    int mid;
    if (arr == NULL || p > q || p == q) {
        return ;
    }
    mid = (p + q) / 2;
    //将 [p,q] 分为[p,mid] 和 [mid+1,q] 区域
    merge_sort(arr, p, mid);
    merge_sort(arr, mid + 1, q);
    //对分好的 [p,mid] 和 [mid,q] 进行归并操作
    merge(arr, p, mid, q);
}
//实现归并操作的函数,归并的 2 个区域分别为 [p,mid] 和 [mid+1,q]
void merge(int* arr, int p, int mid, int q) {
    int i,j,k;
    int leftarr[100], rightarr[100];
    int numL = mid - p + 1;
    int numR = q - mid;
    //将 arr 数组中 [p,mid] 区域内的元素逐一拷贝到 leftarr 数组中
    for (i = 0; i < numL; i++) {
        leftarr[i] = arr[p - 1 + i];
    }
    //将 arr 数组中 [mid+1,q] 区域内的元素逐一拷贝到 rightarr 数组中
    leftarr[i] = 2147483647;
    for (i = 0; i < numR; i++) {
        rightarr[i] = arr[mid + i];
    }
    rightarr[i] = 2147483647;
    i = 0;
    j = 0;
    //逐一比较 leftarr 和 rightarr 中的元素,每次将较小的元素拷贝到 arr 数组中的 [p,q] 区域内
    for (k = p; k <= q; k++) {
        if (leftarr[i] <= rightarr[j]) {
            arr[k - 1] = leftarr[i];
            i++;
        }
        else {
            arr[k - 1] = rightarr[j];
            j++;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/227535
推荐阅读
相关标签
  

闽ICP备14008679号