首页 > 编程语言 >C#学习笔记本--第三篇(排序算法之归并排序)

C#学习笔记本--第三篇(排序算法之归并排序)

时间:2024-08-30 15:52:19浏览次数:10  
标签:right C# Length -- int 数组 array 排序 left

一、基本原理:

//归并 = 递归 + 合并

//数组分左右 
//左右元素相比较
//满足条件放入新数组
//一侧用完放对面

//递归不停分 分完在排序
//排序结束往上走 边走边合并
//走到头顶出结果

//归并排序分为两部分
//1.基本排序规则
//2.递归平分数组

//递归平分数组:
//不停地分割,长度小于2停止
//开始比较
//一层一层向上比较

//基本排序规则:
//左右元素进行比较
//依次放入新数组
//一侧没有了另一侧直接放入新数组

二、图像说明原理

        这是原始数组,由于是不断的平分数组,所以除以二取整就是4第一次分割为,8 7 1 5 和 4 2 6 3 9 两个部分

继续向下分割直到分为每个新数组只有一个元素为止

切割完毕后我们就可以开始排序了,这里我们选择升序排列

        这里以8 7为例介绍 left为一个数组 right为一个数组,用来记录取的元素。在这里,由于我们是进行升序排列,所以left数组第0个元素和right数组第0个元素相比较,由于right数组第0个元素小于left第0个元素,所以先把7放到新数组,然后right加一,此时由于该元素7已经放入新数组了。所以right数组元素为空,故直接将left数组元素全部放入新数组,然后left加一。这里比较完毕后,同时本轮的其他成员也会进行比较。

 

接下来我们比较6 3 9  由于3 9 在下一层次,所以得先将3 9 自己比较完毕后才能和6比较,这连个元素的比较方法和前面一样不赘述。将获得的新数组和6进行一一比较排序

 这里,将3 9 获得的新数组与6进行比较排序,右边第0个元素3小于6放入到新数组,然后right+1,然后继续比较左边第0个元素和右边第1个元素,发现6<9所以将6放入到新数组,left+1,此时左边数组没有元素了,直接将右侧元素全部放入即可然后right再+1

如此反复即可得到一个最终有序的数组,所以我们需要用到递归的思想,反复调用代码。

三、代码实现 

①先得有一个数组

 int[] arr = new int[] { 8, 7, 1, 5, 4, 2, 6, 3, 9 };

 ②由于之前不断的需要将数组平分和排序,这里需要不断的递归自己,所以肯定不能想到在主函数里面进行代码的编写,肯定需要另外单独写函数,然后调用。需要排序函数和平分函数。先来写排序函数。

        怎么写呢 由于需要将元素重新装到一个新数组,所以得申明一个新数组 和左右索引,而这个函数的目的是为了排序左右数组最后返回一个新数组,所以返回值是int[],传参是两个数组,新数组的长度肯定不会超过左右两个数组的长度之和,所以这样申明

public static int[] Sort(int[] left, int[] right)
{ 
    //先准备一个新数组
    int[] array = new int[left.Length + right.Length];
    int leftIndex = 0;
    int rightIndex = 0;

  
    return array;
}

这是整体框架,然后我们想着写排序逻辑,由于需要获取到每个元素,所以我们利用for循环获取每个元素。

 for (int i = 0; i < array.Length; i++)
 {
 
 }

现在可以在里面写排序逻辑了。

有什么条件可以写呢

1.左边放完了直接放右边元素

//意味着左侧数组已经全部放入新数组 该放对面了
if (leftIndex >= left.Length)
{ 
    array[i] = right[rightIndex];
    rightIndex++;
}

 2.右边放完了直接放左边元素

  //意味着右侧数组已经全部放入新数组 该放对面了
  else if (rightIndex >= right.Length)
  {
      array[i] = left[leftIndex];
      leftIndex++;
  }

3.右边元素大于左边元素将左边元素放入新数组

 else if (left[leftIndex] < right[rightIndex])
 { 
     array[i] = left[leftIndex];
     //已经放入了一个左侧元素进入新数组
     //所以标识指向下一个
     leftIndex++;
 }

4左边元素大于右边元素将右边元素放入新数组

 else
 {
     array[i] = right[rightIndex];
     //已经放入了一个右侧元素进入新数组
     //所以标识指向下一个
     rightIndex++;
 }

 最后将数组返回出去即可

排序函数完整代码:

public static int[] Sort(int[] left, int[] right)
{ 
    //先准备一个新数组
    int[] array = new int[left.Length + right.Length];
    int leftIndex = 0;
    int rightIndex = 0;

    //最终目的是填满这个新数组
    //不会出现两侧都放完了 还在进循环
    //因为这个新数组的长度 是根据左右两个数组的长度计算出来的
    for (int i = 0; i < array.Length; i++)
    {
        //意味着左侧数组已经全部放入新数组 该放对面了
        if (leftIndex >= left.Length)
        { 
            array[i] = right[rightIndex];
            rightIndex++;
        }
        //意味着右侧数组已经全部放入新数组 该放对面了
        else if (rightIndex >= right.Length)
        {
            array[i] = left[leftIndex];
            leftIndex++;
        }
        else if (left[leftIndex] < right[rightIndex])
        { 
            array[i] = left[leftIndex];
            //已经放入了一个左侧元素进入新数组
            //所以标识指向下一个
            leftIndex++;
        }
        else
        {
            array[i] = right[rightIndex];
            //已经放入了一个右侧元素进入新数组
            //所以标识指向下一个
            rightIndex++;
        }
    
    }

    //得到了新数组 直接返回新数组
    return array;
}

③接下来写平分函数  由于最后传出的是最终结果 要把最初的数组传入 然后平分 所以这样申明

 public static int[] Merge(int[] array)
 {
    
}

1. 初始化

 //1.数组分两段 得到一个中间索引
 int mid = array.Length / 2;

 //2.初始化左右数组
 //左数组
 int[] left = new int[mid];
 //右数组
 int[] right = new int[array.Length - mid];
 //左右初始化内容
 for (int i = 0; i < array.Length; i++)
 {
     if (i < mid)
         left[i] = array[i];
     else
         right[i - mid] = array[i];
 }

2.这里是不是就获取到了两个数组,只要将他们不断的平分平分再平分就可以得到最小的数组然后进行排序,关键代码

 //3.递归再分再排序
 return Sort(Merge(left), Merge(right));

3.由于是在递归自己,需要有结束条件,结束条件写在函数最开始,不过咱们需要怎样的结束条件呢,当然是数组长度小于2时

 

 //递归结束条件
 if (array.Length < 2)
 { 
     return array;
 }

该函数完整代码:

public static int[] Merge(int[] array)
{
    //递归结束条件
    if (array.Length < 2)
    { 
        return array;
    }
    //1.数组分两段 得到一个中间索引
    int mid = array.Length / 2;

    //2.初始化左右数组
    //左数组
    int[] left = new int[mid];
    //右数组
    int[] right = new int[array.Length - mid];
    //左右初始化内容
    for (int i = 0; i < array.Length; i++)
    {
        if (i < mid)
            left[i] = array[i];
        else
            right[i - mid] = array[i];
    }
    //3.递归再分再排序
    return Sort(Merge(left), Merge(right));
}

四、运行结果

五、总结

//基本原理 归并=递归+合并
//数组分左右 左右元素相比较
//一侧用完放对面
//不停放入新数组

//递归不停分
//分完在排序
//排序结束往上走
//边走边合并
//走到头顶出结果

//套路写法
//两个函数
//一个基本排序规则
//一个递归平分数组

//注意事项
//排序规则函数 在平分数组函数里调用
//内部return调用

六、完整代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 归并排序
{
    internal class Program
    {
        static void Main(string[] args)
        {
            int[] arr = new int[] { 8, 7, 1, 5, 4, 2, 6, 3, 9 };
            arr = Merge(arr);
            for (int i = 0; i < arr.Length; i++)
            {
                Console.WriteLine(arr[i]);
            }
            Console.ReadKey();

        }

        #region  归并排序的代码实现
        
        //第一步:
        //基本排序规则
        //左右元素进行比较
        //满足条件放进去
        //一侧没有了放对面
        public static int[] Sort(int[] left, int[] right)
        { 
            //先准备一个新数组
            int[] array = new int[left.Length + right.Length];
            int leftIndex = 0;
            int rightIndex = 0;

            //最终目的是填满这个新数组
            //不会出现两侧都放完了 还在进循环
            //因为这个新数组的长度 是根据左右两个数组的长度计算出来的
            for (int i = 0; i < array.Length; i++)
            {
                //意味着左侧数组已经全部放入新数组 该放对面了
                if (leftIndex >= left.Length)
                { 
                    array[i] = right[rightIndex];
                    rightIndex++;
                }
                //意味着右侧数组已经全部放入新数组 该放对面了
                else if (rightIndex >= right.Length)
                {
                    array[i] = left[leftIndex];
                    leftIndex++;
                }
                else if (left[leftIndex] < right[rightIndex])
                { 
                    array[i] = left[leftIndex];
                    //已经放入了一个左侧元素进入新数组
                    //所以标识指向下一个
                    leftIndex++;
                }
                else
                {
                    array[i] = right[rightIndex];
                    //已经放入了一个右侧元素进入新数组
                    //所以标识指向下一个
                    rightIndex++;
                }
            
            }

            //得到了新数组 直接返回新数组
            return array;
        }
        //第二步:
        //递归平分数组
        //不停地分割,长度小于2停止
        public static int[] Merge(int[] array)
        {
            //递归结束条件
            if (array.Length < 2)
            { 
                return array;
            }
            //1.数组分两段 得到一个中间索引
            int mid = array.Length / 2;

            //2.初始化左右数组
            //左数组
            int[] left = new int[mid];
            //右数组
            int[] right = new int[array.Length - mid];
            //左右初始化内容
            for (int i = 0; i < array.Length; i++)
            {
                if (i < mid)
                    left[i] = array[i];
                else
                    right[i - mid] = array[i];
            }
            //3.递归再分再排序
            return Sort(Merge(left), Merge(right));
        }
        #endregion



}

标签:right,C#,Length,--,int,数组,array,排序,left
From: https://blog.csdn.net/m0_74212916/article/details/141717588

相关文章

  • KubeSphere 社区双周报| 2024.08.16-08.29
    KubeSphere社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过commit的贡献者,并对近期重要的PR进行解析,同时还包含了线上/线下活动和布道推广等一系列社区动态。本次双周报涵盖时间为:2024.08.16-08.29。贡献者名单新晋KubeSpherecontribu......
  • 高精度,强扭矩,舵机让每一次转动都精准无误!
    深入探索科技的前沿,我们不得不聚焦于一款革新性的动力核心——高精度、强扭矩的舵机。这项技术杰作,以其精湛的工艺与尖端的技术,重新定义了精密控制的新标准,无论是翱翔天际的航模,还是穿梭于复杂任务中的机器人手臂,都因它而焕发出前所未有的活力与精准。核心技术解析:高精度舵机......
  • C++ 快速输入的优化与缓冲区管理(竞赛必用)
    在编程竞赛和性能敏感的场景中,数据输入的效率往往直接影响到程序的运行速度。为了优化输入操作,我们可以通过手动设定缓冲区的方式来提升输入的速度。本文将详细介绍两种不同的快速输入方案:手动设定缓冲区大小的方案与系统默认缓冲区大小的方案,并结合二进制位数与可表示数据范围......
  • .NET 摄像头采集及多种方案对比
    本文主要介绍摄像头(相机)如何采集数据,用于类似摄像头本地显示软件,以及流媒体数据传输场景如传屏、视讯会议等。摄像头采集有多种方案,如AForge.NET、WPFMediaKit、OpenCvSharp、EmguCv、DirectShow.NET、MediaCaptre(UWP),网上一些文章以及github已经有很多介绍,这里总结、确认技术选......
  • 推荐几个超级好用的HID调试工具
    最近有调试HID的任务,所以搜罗了市面上目前的一些HID调试工具,其中有几个很好用的,使用体验不错,但是也有些小问题,也一并提出来,大家自行选择~1.纸飞机调试助手大名鼎鼎的纸飞机的确是好用,界面布局清晰,显示一目了然,功能完整。纸飞机对文本做了语法高亮,字母、数字、符号之间的颜......
  • Fibonacci 第 n 项
    //Fibonacci第n项.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。///*https://loj.ac/p/10220题目描述大家都知道Fibonacci数列吧,f_1=1,f_2=1,f_3=2,f_4=3,~~~,f_n=f_{n-1}+f_{n-2}。现在问题很简单,输入n和m,求f_nmodm。输入格式输入n,m。......
  • 【CSP】坐标变换2(问题拆解,快速输入,知识补充)
    1.题目背景与任务分析题目背景本题要求对二维平面上的点进行指定角度的旋转,并输出旋转后的坐标,要求精确到小数点后六位。这类题目广泛用于考察选手对数学计算、坐标变换以及编程语言中浮点数处理的能力。任务明确输入:多个坐标点及旋转角度。输出:旋转后的新坐标,精确到小数......
  • Vue Cli
    vueCli是基于vue.js进行快速开发的完整系统vue脚手架使用语法:vueinit<模板名称><项目名称>vueinitwebpackvue-spa2安装完成就有项目目录,如下:cdvue-spa2npminstall运行npmrundevbuild构建脚本目录,放置各种配置文件build.js生成环境的构建代码check-versi......
  • 全网最详细爬虫教学-刚学Python也行-方法详解-看我这篇就够了-第一节
        前言        很多人一听到爬虫脑子里就想到黑客,顶级程序员等。但其实爬虫不难,今天,我就来教大家快速入门爬虫。    requests库        说到爬虫,就不得不提request库了,它能提取静态网页源码(静态网页!!!),例如百度就是个静态网站,实战演练一下。......
  • html之form标签的四大护法
    form表单下面的标签记住下面这几个就可以了,常用的也就这么多。1.input--用户名输入框<inputtype="text"name="username"placeholder="用户名">--密码输入框<inputtype="password"name="password"placeholder="密码">--复选框<in......