首页 > 编程语言 >算法学习—归并排序

算法学习—归并排序

时间:2024-11-11 15:17:11浏览次数:3  
标签:归并 int 元素 mid 算法 数组 排序 left

1.算法介绍

  归并算法是一种由冯·诺伊曼发明的分治算法,相较于普通排序算法时间复杂度较低,运行效率高。通常情况下,归并算法的时间复杂度为 O(nlogn)。

2.算法思想以及大致步骤

  归并算法主要运用到了分治以及归并的思想,主要步骤如下:首先将一个无序数组分为n个有序的单个数组,然后将两个有序的单个数组合并为一个有序的序列,排序过程需要比较两个元素的大小,并按顺序填入心得数组中,不断重复,直到最后得到完全排序后的数组。

3.算法详细步骤以及代码演示

step1:

  假设我们有以下数组[1,5,3,7,4,9,2,8,6,10],第一步,使用递归算法将该数组不断地由数组中间一分为二,直到得到只有单个元素的数组[1],[5],[3],[7],[4],[9],[2],[8],[6],[10],要注意,理解归并算法的核心就是:在此时,所有单个元素的数组都是有序的。递归分解算法如下:

void mergesoft(int arr[],int left,int right){
    if (right-left<=1)//判断是否为单个元素数组
    {
        return 0 ;

    }
    int mid = (left+right)/2;//将数组一分为二
    mergesoft(arr,left,mid);//对数组左半部分进行递归分解
    mergesoft(arr,mid,right);//对数组右半部分进行递归分解
    merge(arr,left,mid,right);//归并排序函数
}

step2:

  开始进行归并排序,将两个单个有序数组进行按照数值大小进行排序,按照从小到大的顺序放入一个新数组中,以此类推,我们以归并到两个有序数组后为例:此时经过前面的归并排序,我们可以得到两个有序数组a[1,3,6,8,10],b[2,4,5,7,9],下一步需要将两个数组合并为一个有序数组。首先,我们先创建一个新数组temp,用于临时存放排好序的新数组的元素,现在就可以对两个数组进行排序了,我们定义指向a数组最左边元素的指针为left,指向b数组最左边元素的指针为mid,最右边元素的指针为right,指向临时数组的指针为index。比较left和mid指针所指向的元素,此时left指针指向的元素为1,mid指针指向的元素为2,left指向的元素较小,将a[left]赋予temp[index],注意,由于将left指向的元素赋予给了index,所以我们需要将left和index指针向右移动一位才能进行继续比较下一个元素,否则新的元素无法存放入新数组中。现在left指针指向3,mid指针依然指向2,mid指向的元素小于left指向的元素,所以将b[mid]赋予temp[index],注意,赋值后,right和index指针同样需要向右移动一位。以此类推,直到所有的元素按顺序存放入临时数组temp中,排序完成,但是我们的任务还没有完成,我们需要将临时数组的值赋予我们需要排序的数组中,并将临时数组进行释放,避免占用过多内存,影响代码的性能。归并排序代码如下:

void merge(int arr[],int left,int mid,int right){//left,right,mid分别为数组的左右边界和中间元素
    int i =left;
    int j =mid;
    int*temp = (int*)malloc((right-left)*sizeof(int));//定义一个临时数组
    int index = 0;//将临时数组的索引指向0

    while (i<mid && j <right)//判断指针是否越过边界
    {
        if (arr[i]<arr[j])//如果左边数组的元素小于右边
        {
            temp[index]=arr[i];//将左边数组元素赋予临时数组
            i++;//指针右移一位
        }else{
            temp[index]= arr[j];//将右边数组元素赋予临时数组
            j++;//指针右移一位
        }
        index++;//临时数组指针同时右移一位
    }
    while (i<mid)//将排序完剩余的元素全部写入临时数组中
    {
            temp[index]=arr[i];
            index++;
            i++;
    }
    while (j<right)
    {
            temp[index]=arr[j];
            index++;
            j++;
    }
    for ( int i = 0; i < index; i++)//将临时数组中的所以元素写入原来数组中
    {
        arr[left+i] = temp[i];
    }
    free(temp);//释放内存

}

完成归并排序

4.完整代码演示:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void merge(int arr[],int left,int mid,int right){
    int i =left;
    int j =mid;
    int*temp = (int*)malloc((right-left)*sizeof(int));
    int index = 0;

    while (i<mid && j <right)
    {
        if (arr[i]<arr[j])
        {
            temp[index]=arr[i];
            
            i++;
        }else{
            temp[index]= arr[j];
            j++;
        }
        index++;
    }
    while (i<mid)
    {
        temp[index]=arr[i];
        index++;
        i++;
    }
    while (j<right)
    {
        temp[index]=arr[j];
        index++;
        j++;
    }
    for ( int i = 0; i < index; i++)
    {
        arr[left+i] = temp[i];
    }
    free(temp);

}
void mergesoft(int arr[],int left,int right){
    if (right-left<=1)
    {
        return 0 ;

    }
    int mid = (left+right)/2;
    mergesoft(arr,left,mid);
    mergesoft(arr,mid,right);
    merge(arr,left,mid,right);
}


void printfarray(int *arr,int size){
    for (int i = 0; i < size; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
}

    


int main(){
    clock_t start, end;
    double cpu_time_used;

    start = clock();
    srand((unsigned int)time(NULL));
    int array5[5];
    int array10[10];
    int array100[100];
    int i,j,k;
    printf("array5:\n");
    for(i=0;i<5;i++){
        array5[i] = rand()%1000000000;
        printf("%d ", array5[i]);
        printf("\n");
    }
   
    printf("array10:\n");
    for(j=0;j<10;j++){
        array10[j]=rand()%100000000;
        printf("%d ", array10[j]);
        printf("\n");
    }
    printf("array100:\n");
    for(k=0;k<100;k++){
        array100[k]=rand()%1000000000;
        printf("%d ", array100[k]);
        printf("\n");
    }
    printf("newarray5");
    printf("\n");
    mergesoft(array5,0,6);
    printfarray(array5,5);
     printf("newarray10");
    printf("\n");
    mergesoft(array10,0,11);
    printfarray(array10,10);
     printf("newarray100");
    printf("\n");
    mergesoft(array100,0,101);
    printfarray(array100,100);
     end = clock();
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;

    printf("The code took %f seconds to execute \n", cpu_time_used);
}

交流学习可联系:[email protected]

标签:归并,int,元素,mid,算法,数组,排序,left
From: https://blog.csdn.net/weixin_74390075/article/details/143684628

相关文章

  • 算法学习—快速排序
    1.算法介绍   快速排序算法是一种高效排序算法,效率相比普通排序算法较高,通常情况下时间复杂度为O(nlogn),但在最坏情况下时间复杂度会提高到O(n^2)2.算法思想和大致步骤 快速排序算法主要用到了二分和递归的思想,主要有三个步骤:(1)在数组中选取一个元素作为基准值(pivot)......
  • 十大经典排序算法-插入排序
    插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑克牌的人都应该能够秒懂。插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排......
  • 区域人数统计视频分析网关算法网关客流统计AI算法介绍及应用场景
    在当今数字化转型的浪潮中,人工智能技术正以其独特的数据处理能力和智能分析优势,深刻改变着各行各业的运作方式。特别是在客流量管理这一领域,AI算法的应用已经成为提升效率、优化决策的关键工具。本文将详细介绍客流量统计AI算法及其在区域人数统计视频分析网关中的应用,展示如何通......
  • 随机化算法
    随机化算法随机化函数rand()srand(seed);intx=rand()%n+1;seed可以是一个常数如114514也可以是时间time(0)。注意,rand()函数在windows系统下返回的取值范围为\([0,2^{15}-1]\),在linux系统下返回的取值范围为\([0,2^{31}-1]\)。mt19937mt19937rd(seed);pf("......
  • 代码随想录算法训练营第十一天 | 150. 逆波兰表达式求值+ 239. 滑动窗口最大值+347.前
    今天接着补上周末的栈与队列的part2,下午继续完成今天的任务。150.逆波兰表达式求值 给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。请你计算该表达式。返回一个表示表达式值的整数。注意:有效的算符为 '+'、'-'、'*' 和 '/' 。每个......
  • 代码随想录算法训练营第十天 | 232.用栈实现队列+225. 用队列实现栈+20. 有效的括号+1
    加入训练营有点晚,没跟上任务就开始有些偷懒没有真的认真开始,从第十天开始下决心认真完成每天任务还有博客记录学习过程。栈与队列理论基础首先是学习了栈和队列的理论基础,队列 先进先出,栈 先进后出。栈 以底层容器完成其所有的工作,且对外接口统一,有.push,.pop等,不提供......
  • (动画版)排序算法 -选择排序
    文章目录1.选择排序(SelectionSort)1.1简介1.2选择排序的步骤1.3选择排序的C实现1.4选择排序的时间复杂度1.5选择排序的空间复杂度1.6选择排序的动画1.选择排序(SelectionSort)1.1简介选择排序(SelectionSort)是一种简单直观的排序算法。它的工作原理是反复......
  • 数组算法练习题
    第一题:寻找锦鲤公司年会有一个寻找锦鲤的游戏,每一个员工随意写一个字,如果在“锦鲤”词库中有这个字,那么就奖励500元锦鲤红包,否则就没有,每人只能玩一次。现有锦鲤字库如下,它们按照Unicode编码值从小到大排序:char[]koiFishWords={'一','今','地','定','年','开','我','果','......
  • [数组排序] 0384. 打乱数组
    文章目录1.题目大意2.题目大意3.示例4.解题思路5.参考代码1.题目大意384.打乱数组-力扣(LeetCode)2.题目大意描述:给定一个整数数组nums。要求:设计算法来打乱一个没有重复元素的数组。打乱后,数组的所有排列应该是等可能的。实现Solutionclass:Sol......
  • 算法性能测试基础
    算法的性能测试是一个综合评估算法在不同条件下的表现和效率的过程。在进行算法性能测试时,需要关注多个关键指标,以确保全面、准确地评估算法的性能。以下是对算法性能测试的详细解释和需要关注的指标的归纳:一、算法性能测试概述算法性能测试的目的是验证算法在各种输入情况下的......