首页 > 其他分享 >快速排序和归并排序

快速排序和归并排序

时间:2024-07-21 17:55:18浏览次数:10  
标签:归并 right end int begin 排序 快速 left

目录

一、序言

二、快速排序

1.介绍

2.思路

3.代码实现

三、归并排序

1.介绍

2.思路

3.代码实现

四、小结


一、序言

快速排序和归并排序是我认为很常用的两个排序,而很多人对此仍然存在一些疑问与不解,所以今天让我带大家重新回顾一下这两个排序的代码实现。

二、快速排序

1.介绍

快速排序的原理基于分治法的思想,通过递归地将一个数组分成两个(或更多)较小的子数组,直到子数组的大小为1或0,此时子数组自然是有序的。然后,算法将这些有序的子数组合并成一个大的有序数组,但在这个特定的情况下,由于子数组已经是有序的,并且它们是按照大小顺序排列的(一个子数组中的所有元素都小于另一个子数组中的所有元素),所以合并步骤实际上不需要进行任何操作,整个数组就已经是有序的了。

2.思路

快速排序思路:(先排序再递归)

Step1. 定义left,right作为双指针(这么说可能不准确,但大概就是这个意思),一个从头遍历,一个从尾遍历。

Step2. 选择数据中一个数为参考值(一般默认第一个数的值),这里记作target。

Step3. 让left,right对应数据的值分别与之进行比较

           若left对应的值小于target就向后遍历,直到大于等于target时停下;

           若right对应的值大于target就向前遍历,直到小于等于target时停下。

           当left与right都停下时,交换left与right对应的数据的值。

Step4. 重复以上操作,直到两者相遇。

           两者会相遇到此时的right处,我们以right为界,同样对其左右序列进行相同排序操作(递               归)。循环往复,直至排序成功。

3.代码实现

快排函数部分:

void quick_sort(int begin,int end)
{
       if(begin >= end)     return ;      //注意
       int left = begin;    
       int right = end;
       int target = a[begin];      
       while(left < right)
       {
              while(a[left] < target)    left++;       //注意是while,而不是if(while在这里表示一直移动,直到不满足时才停止)
              while(a[right] > target)   right--;
              if(left < right)       swap(a[left],a[right]);       //这里必须要再次强调left < right,这样就避免了最后相遇的情况
       }
       //递归操作,对right左右区间进行同样操作(此时right左边全小于target,右边全大于target)
       quick_sort(begin,right);
       quick_sort(right+1,end);
}

完整代码:

#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N], n;
void quick_sort(int begin,int end)
{
       if(begin >= end)     return ;      
       int left = begin;    
       int right = end;
       int target = a[begin];      
       while(left < right)
       {
              while(a[left] < target)    left++;       
              while(a[right] > target)   right--;
              if(left < right)       swap(a[left],a[right]);       
       }
       quick_sort(begin,right);
       quick_sort(right+1,end);
}

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++)    scanf("%d", &a[i]);
    quick_sort(0, n - 1);
    for (int i = 0; i < n; i++)    printf("%d ", a[i]);
    return 0;
}

三、归并排序

1.介绍

归并排序的基本思想是将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

2.思路

归并排序--分治思想:(先递归再排序)

Step1. 定义tmp数组用于存放已经排好序的数据(放第一步主要是让后续思路更清晰)

Step2. 将原数组(我把它记作a[])数据分成两半:左区间(begin,mid)与 右区间(mid+1,end)

Step3. 递归,分别对左右两区间进行同样操作(这里直接调用该函数)--这里其实也好理解:

           因为归并排序是先分成两部分,这两部分再分别细分左区间和右区间,一直分到不能

           分为止,然后再按小块排序,排完序后再不断合并进行整体排序

Step4. 建立i,j,k

           i表示左区间起点;j表示右区间起点;k表示tmp数组下标,从最初(begin)开始

Step5. i处于左区间且j处于右区间(两区间的元素都还没全存入tmp数组)时,tmp数组用于存放                两者较小值,然后存放的值对应的i或j进行相应移动(i右移或j左移)

Step6. 当j不在右区间时或i不在左区间时(即某个区间的数全都已经排完序,存入tmp中了),

           这时只需要把剩下那个区间的数挨个填进tmp数组后边就行了

Step7. 最后不要忘记将tmp数组的值赋给原数组(a[])

3.代码实现

归并排序函数部分:

void merge_sort(int begin, int end) {
    int tmp[N];             //定义tmp数组用来存放已经排好序的数据

    if (begin >= end) return ;      //注意

    int mid = begin + end >> 1;         //位运算 >> 等价于除以2,将数据(数组)分成两半:左(begin,mid)与 右(mid+1,end)
    merge_sort(begin, mid);             //先递归,对左右区间进行同样操作
    merge_sort(mid + 1, end);

    int i = begin, j = mid + 1, k = begin;      //i,j分别初始化在左右区间起点处 ,k作为tmp数组序标,初始化为begin
    while (i <= mid && j <= end)        //循环条件:i在左区间 且 j在右区间(两个区间的数都还没排完序存入tmp数组中)
    {
        if (a[i] <= a[j])
            tmp[k ++ ] = a[i ++ ];          //tmp数组用于记录a[i]与a[j]两者的较小值,较小值对应的i或j进行+1,每次赋值后k++
        else    
            tmp[k ++ ] = a[j ++ ];
    }
    //j不在右区间时 或 i不在左区间时(即某个区间的数全都已经排完序,存入tmp中了),这时只需要把剩下那个区间的数挨个填进去就行
    while (i <= mid)    tmp[k ++ ] = a[i ++ ];
    while (j <= end)  tmp[k ++ ] = a[j ++ ];

    for (int i = begin; i <= end; i ++ )  
        a[i] = tmp[i];              //不要忘,这样就将a[i]排好序了
}

完整代码:

#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N],  n;

void merge_sort(int begin, int end) 
    int tmp[N];             

    if (begin >= end) return ;      

    int mid = begin + end >> 1;         
    merge_sort(begin, mid);             
    merge_sort(mid + 1, end);

    int i = begin, j = mid + 1, k = begin;     
    while (i <= mid && j <= end)       
    {
        if (a[i] <= a[j])
            tmp[k ++ ] = a[i ++ ];         
        else    
            tmp[k ++ ] = a[j ++ ];
    }
    while (i <= mid)    tmp[k ++ ] = a[i ++ ];
    while (j <= end)  tmp[k ++ ] = a[j ++ ];

    for (int i = begin; i <= end; i ++ )  
        a[i] = tmp[i];              
}

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; ++ i)   scanf("%d", &a[i]);
    merge_sort(0, n - 1);
    for (int i = 0; i < n; ++ i)   printf("%d ", a[i]);
    return 0;
}

四、小结

以上就是我对于快速排序和归并排序的一些理解,希望能够帮助到你。明天将继续更新代码随想录训练营的打卡,希望我能够坚持下去。我是算法小白,但也希望终有所获。

标签:归并,right,end,int,begin,排序,快速,left
From: https://blog.csdn.net/2303_79786049/article/details/140590520

相关文章

  • 指令重排序
    CPU内部结构图例CPU由多个功能部件构成在这个结构中,一条指令执行时,要依次用到多个功能部件,分成多个阶段,虽然每条指令是顺序执行的,但每个部件的工作完成以后,就可以服务于下一条指令,从而达到并行的效果这种结构叫做流水线(pipeline)结构流水线(pipeline)结构比如典型的......
  • 【Rollup】快速上手及其配置
    概述Rollup是一款使用ESModules标准的JavaScript打包工具。它也可以将项目中散落的细小模块打包为整块代码。从作用上来看,Rollup与Webpack非常类似。不过相比于Webpack,Rollup要小巧的多。因为Webpack在配合一些插件的使用下,几乎可以完成开发过程中,前端工程化......
  • 常见的排序算法——堆排序(四)
    本文记述了针对堆排序同时实施减少数据交换和Floyd方法的一份参考实现代码,并在说明了算法的性能后用随机数据进行了验证。◆思想减少数据交换的操作,请参考堆排序(二);Floyd方法,请参考堆排序(三)(此处略去详细说明)。◆实现排序代码采用《算法(第4版)》的“排序算法类模板”实现。(......
  • Mike11前处理—如何快速简便的提取断面文件Cross sections?——ZDM法
    前言:近期接触了一些关于MIKE11提取断面的技巧,当然很多人应该知道这种方法——ZDM软件提取(一款水工设计软件)。我们一般拿到都是CAD版本的断面文件,如果一个一个去输入的话,繁琐又耗时,还容易出错,今天我们在这里介绍一种简单的断面提取方法—ZDM法此方法适用很普遍,小编抽个时......
  • 常见的排序算法——堆排序(三)
    本文记述了针对堆排序实施Floyd方法的基本思想和一份参考实现代码,并在说明了算法的性能后用随机数据进行了验证。◆思想“大多数在下沉排序期间重新插入堆的元素会被直接加入到堆底。Floyd在1964年观察发现,我们正好可以通过免去检查元素是否到达正确位置来节省时间。”(引......
  • 从 Pandas 到 Polars 二十三:如果你的数据已经排序,Polars可以为你提供助力
    Polars针对处理已排序的数据进行了优化。要访问这些优化,你需要使用set_sorted标志告诉Polars数据已经排序。set_sorted主要用于以下两种情况:标记单个或多个列已排序:当你知道DataFrame的某个或某些列是按升序或降序排列时,你可以使用set_sorted来标记这些列。这将告诉P......
  • 如何使用FlowUs快速构建专业领域知识网络是一个系统化的过程,旨在整合和组织一个特定领
     在这个信息爆炸的时代,快速构建知识网络就像是在浩瀚的知识海洋中搭建一座灯塔,指引我们前行的方向。它不仅帮助我们系统化地整理和理解复杂的信息,还能让我们在专业领域内更快速地成长和进步。当你面对一个全新的项目或挑战时,拥有一个完善的知识网络就像是拥有了一个强大的后......
  • 七大排序算法的Python实现
    七大排序算法的Python实现1.冒泡排序(BubbleSort)算法思想冒泡排序通过重复交换相邻的未按顺序排列的元素来排序数组。每次迭代都将最大的元素“冒泡”到数组的末尾。复杂度分析时间复杂度:O(n^2)空间复杂度:O(1)defbubble_sort(arr):n=len(arr)for......
  • 排序
    define_CRT_SECURE_NO_WARNINGS1include"mySort.h"voidmySort::printArr(vector&vec){for(constauto&i:vec){cout<<i<<"";}}voidmySort::BubbleSort(vector&vec){for(intj=vec.size()-1;j>=......
  • 各种快速排序-史诗级巨作
    定义快速排序(英语:Quicksort),又称分区交换排序(英语:partition-exchangesort),简称「快排」,是一种被广泛运用的排序算法。基本原理与实现过程快速排序的工作原理是通过分治的方式来将一个数组排序。快速排序分为三个过程:将数列划分为两部分(要求保证相对大小关系);递归到两个子序......