项目 1 - 验证算法之(7)归并排序

本文介绍了一种使用C语言实现的归并排序算法,并通过一个具体的例子展示了如何对一组无序的数据进行排序。该程序首先定义了记录类型,然后通过递增的归并过程逐步实现对整个序列的有效排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/* 


*Copyright (c) 2016,烟台大学计算机学院 
*All right reserved.  
  
*文件名称:test.cpp  
  
*作者:杨天瑞  
  
*完成日期:2016年12月17日  
  
*版本号:v1.8.4
   
*  
  
*  问题描述:用序列{57, 40, 38, 11, 13, 34, 48, 75, 6, 19, 9, 7}作为测试数据,运行并视频中算法对应 程序,观察运行结果并深刻领会算法的思路和实现方法。
             


*  程序输入:无。
  
*  程序输出:排序结果。  
  

*/


guibing.cpp:



#include <stdio.h>
#include <malloc.h>
#define MaxSize 20
typedef int KeyType;    //定义关键字类型
typedef char InfoType[10];
typedef struct          //记录类型
{
    KeyType key;        //关键字项
    InfoType data;      //其他数据项,类型为InfoType
} RecType;              //排序的记录类型定义

void Merge(RecType R[],int low,int mid,int high)
{
    RecType *R1;
    int i=low,j=mid+1,k=0; //k是R1的下标,i、j分别为第1、2段的下标
    R1=(RecType *)malloc((high-low+1)*sizeof(RecType));  //动态分配空间
    while (i<=mid && j<=high)       //在第1段和第2段均未扫描完时循环
        if (R[i].key<=R[j].key)     //将第1段中的记录放入R1中
        {
            R1[k]=R[i];
            i++;
            k++;
        }
        else                            //将第2段中的记录放入R1中
        {
            R1[k]=R[j];
            j++;
            k++;
        }
    while (i<=mid)                      //将第1段余下部分复制到R1
    {
        R1[k]=R[i];
        i++;
        k++;
    }
    while (j<=high)                 //将第2段余下部分复制到R1
    {
        R1[k]=R[j];
        j++;
        k++;
    }
    for (k=0,i=low; i<=high; k++,i++) //将R1复制回R中
        R[i]=R1[k];
}

void MergePass(RecType R[],int length,int n)    //对整个数序进行一趟归并
{
    int i;
    for (i=0; i+2*length-1<n; i=i+2*length)     //归并length长的两相邻子表
        Merge(R,i,i+length-1,i+2*length-1);
    if (i+length-1<n)                       //余下两个子表,后者长度小于length
        Merge(R,i,i+length-1,n-1);          //归并这两个子表
}
void MergeSort(RecType R[],int n)           //自底向上的二路归并算法
{
    int length;
    for (length=1; length<n; length=2*length) //进行log2n趟归并
        MergePass(R,length,n);
}
int main()
{
    int i,n=10;
    RecType R[MaxSize];
    KeyType a[]= {9,8,7,6,5,4,3,2,1,0};
    for (i=0; i<n; i++)
        R[i].key=a[i];
    printf("排序前:");
    for (i=0; i<n; i++)
        printf("%d ",R[i].key);
    printf("\n");
    MergeSort(R,n);
    printf("排序后:");
    for (i=0; i<n; i++)
        printf("%d ",R[i].key);
    printf("\n");
    return 0;
}


程序运行截图:

### 递归二路归并排序算法实现 递归二路归并排序是一种基于分治策略的经典排序算法。其核心思想是将待排序序列分为两部分,分别对这两部分进行递归排序,然后再将这两个有序的部分合并成一个整体的有序序列。 以下是递归二路归并排序的具体实现: #### 归并函数 归并函数负责将两个已排序的子数组合并为一个完整的有序数组。该函数通常接收四个参数:原始数组 `arr`、左边界索引 `left`、中间索引 `mid` 右边界索引 `right`。 ```cpp void merge(int arr[], int left, int mid, int right) { int n1 = mid - left + 1; // 左半部分大小 int n2 = right - mid; // 右半部分大小 // 创建临时数组存储左右两部分数据 int L[n1], R[n2]; // 将原数组中的数据复制到临时数组中 for (int i = 0; i < n1; ++i) L[i] = arr[left + i]; for (int j = 0; j < n2; ++j) R[j] = arr[mid + 1 + j]; // 合并两个临时数组回原数组 int i = 0, j = 0, k = left; while (i < n1 && j < n2) { // 自小到大排序 if (L[i] <= R[j]) arr[k++] = L[i++]; else arr[k++] = R[j++]; } // 处理剩余元素 while (i < n1) arr[k++] = L[i++]; while (j < n2) arr[k++] = R[j++]; } ``` 此代码片段展示了如何通过比较左右两部分的数据来完成合并操作[^3]。 #### 递归分割函数 递归分割函数用于将数组不断划分为更小的部分,直到每部分仅剩下一个元素为止。随后调用上述归并函数逐步合并这些部分。 ```cpp void mergeSortRecursive(int arr[], int left, int right) { if (left >= right) // 基本情况:单个元素已经是有序的 return; int mid = left + (right - left) / 2; // 计算中间位置 mergeSortRecursive(arr, left, mid); // 对左侧子数组递归排序 mergeSortRecursive(arr, mid + 1, right); // 对右侧子数组递归排序 merge(arr, left, mid, right); // 合并两个有序子数组 } ``` 这段代码实现了递归划分逻辑,并最终利用 `merge` 函数完成了整个数组的排序[^4]。 #### 主函数调用示例 为了方便测试以上实现,可以编写如下主函数来进行验证: ```cpp #include <iostream> using namespace std; // 上述定义的 merge mergeSortRecursive 函数在此处省略... void printArray(const int arr[], int size) { for (int i = 0; i < size; ++i) cout << arr[i] << " "; cout << endl; } int main() { int data[] = {38, 27, 43, 3, 9, 82, 10}; int length = sizeof(data) / sizeof(data[0]); cout << "Original array: \n"; printArray(data, length); mergeSortRecursive(data, 0, length - 1); cout << "\nSorted array: \n"; printArray(data, length); return 0; } ``` 运行结果会展示未排序经过递归二路归并排序后的数组状态。 时间复杂度方面,由于每次都将输入规模减半并且执行线性的合并工作量,所以总体性能表现为 O(n log n)[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值