归并排序_C

 //   维基百科

归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用

算法描述

归并操作的过程如下:

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列                                                          
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
  3. 重复步骤3直到某一指针达到序列尾
  4. 将另一序列剩下的所有元素直接复制到合并序列尾

分类排序算法
数据结构数组
最差时间复杂度Θ(nlog n)
最优时间复杂度Θ(n)
平均时间复杂度Θ(nlog n)
最差空间复杂度Θ(n)
最佳算法有时是

 

算法思路:

1.假设数组 a[ 10 ] = {26,5,37,1,61,11,59,15,48,19, 12}

首先声明一个变量k用于存储数组 a[10]  子序列的长度

初始 k = 1, 表示a数组中每个元素为一个数组

 

2.设定两个位置标志 start1,end1. 表示第一个序列的起始与结束

     start2,end2 表示第二个序列的其实与结束。(注意一个序列并不只有一个元素)

    当k= 1 时, 数组a的序列

     [26] , [5] , [37], [1], [61], [11], [59], [15], [48], [19], [12]  (其中 start1 = 0, end1 = start1 + k - 1, start2 = end1 + 1, end2 = start2 + k - 1)

     一次归并后

      [26, 5] , [37, 1], [1,61], [11,59], [15,48], [19,12]

  

     此时k = 2;  所以每次归并后 k = k*2;

    设置一个循环每次归并后

   start1 = end2 + 1;

   其余值根据start1做出变化,然后 k = k*2;

   直到start1 + k >= size - 1;      size 为数组长度。

 

 

算法代码:

 

/***************************************
*   Function:
*   数据结构_归并排序
*   Lnstree by 2012
****************************************/
#include <stdio.h>

// a[]为待排序的数组 b[]辅助数组 k为子序列的长度 n为数组的大小
void Mpass (int a[], int b[], int k, int n)
{
    int start1,end1;   // 对应第一个有序子序列起始与终止位置
    int start2, end2;  // 对应第二个有序子序列起始与终止位置

    start1 = 0;

    int m = 0;
    int i,j;
    while (start1 + k <= n-1)
    {
        start2 = start1 + k;
        end1 =  start2 - 1;
        end2 = (start2 + k - 1 <= n - 1)? (start2+k-1) : n - 1;

        for (i = start1, j = start2; i<= end1 && j <= end2;)
        {
            if (a[i] <= a[j])
            {
                b[m] = a[i];
                i++;
                m++;
            }
            else
            {
                b[m] = a[j];
                j++;
                m++;
            }
        }

        while (i <= end1)
        {
            b[m] = a[i];
            i++;
            m++;
        }
        while (j <= end2)
        {
            b[m] = a[j];
            j++;
            m++;
        }
        start1 = end2 + 1;
    }
    // 将数组中剩余的元素导入数组
    for (i = start1; i < n; i ++, m++)
    {
        b[m] = a[i];
    }
}

void Msort(int a[], int b[], int n)
{
    int i,k,count;
    k = 1;
    count = 1;
    while (k < n)
    {
        Mpass(a,b,k,n);   //  归并两个子序列

        for (i = 0; i < n; i++)
        {
            a[i] = b[i];
        }
        printf ("\n第%2d操作后:", count++);
        for (i = 1; i < n + 1; i++)
        {
            if ((i==n) && ((i%(2*k) != 0)))
            printf("%5d]", a[i-1]);
            else
            {
                if (i%(2*k) == 1)
                {
                    printf("[%2d", a[i - 1]);
                }
                else if (i%(2*k) == 0)
                {
                    printf("%4d]", a[i - 1]);
                }
                else
                {
                    printf("%4d", a[i - 1]);
                }
            }
        }
        k = k*2;
    }
}


int main()
{
    int a[10] = {26,5,37,1,61,11,59,15,48,19};
    int b[10];
    int i,j;

    printf("\n源数据:");
    for (i = 0; i < 10; i++)
    {
        printf ("%4d", a[i]);
    }
    Msort(a,b,10);
    printf("\n处理后的数据:");
    for (i = 0; i < 10; i++)
    {
        printf ("%4d", a[i]);
    }
    return 0;
}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
归并排序是一种常见的排序算法,它采用分治的思想,将一个大问题分解为多个小问题进行解决,最后将结果合并得到有序序列。下面是归并排序的步骤: 1. 分解:将待排序的序列不断二分,直到每个子序列只有一个元素。 2. 合并:将相邻的子序列两两合并,得到更大的有序子序列。 3. 重复合并:重复步骤2,直到所有子序列合并为一个完整的有序序列。 下面是一个使用C语言实现的归并排序的例子: ```c #include <stdio.h> // 合并两个有序数组 void merge(int arr[], int left, int mid, int right) { int i, j, k; int n1 = mid - left + 1; int n2 = right - mid; // 创建临时数组 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[mid + 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++; } } // 归并排序 void mergeSort(int arr[], int left, int right) { if (left < right) { int mid = left + (right - left) / 2; // 分解为子问题 mergeSort(arr, left, mid); mergeSort(arr, mid + 1, right); // 合并子问题的解 merge(arr, left, mid, right); } } // 打印数组 void printArray(int arr[], int size) { int i; for (i = 0; i < size; i++) printf("%d ", arr[i]); printf("\n"); } int main() { int arr[] = {12, 11, 13, 5, 6, 7}; int size = sizeof(arr) / sizeof(arr[0]); printf("原始数组:"); printArray(arr, size); mergeSort(arr, 0, size - 1); printf("排序后的数组:"); printArray(arr, size); return 0; } ``` 这段代码实现了归并排序算法。首先,通过`merge`函数将两个有序的子数组合并为一个有序的数组。然后,通过mergeSort`函数将待排序的数组不断分解为更小的子数组,并最终合并得到有序的结果。最后,通过`printArray`函数打印排序后的数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值