1-1排序算法专题

0 常见排序算法总结

基础排序算法: 冒泡排序、选择排序、插入排序归并排序、希尔排序、快速排序堆排序

建议看不懂原理说明或图示时请看代码。

1. 冒泡排序

1.1 基本思想

冒泡排序是一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。

算法描述:

  1. 比较相邻两个数据如果。第一个比第二个大,就交换两个数
  2. 对每一个相邻的数做同样1的工左,这样从开始一队到结尾一队在最后的数就是最大的数。
  3. 针对所有元素上面的操作,除了最后一个。
  4. 重复1~3步骤,知道顺序完成。

1.2 图解

1.3 代码

/*    1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。    2. 对第0个到第n-1个数据做同样的工作。这时,最大的数就“浮”到了数组最后的位置上。    3. 针对所有的元素重复以上的步骤,除了最后已经选出的元素(有序)。    4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较.*/// 稳定排序,平均 O(n**2),最好 O(n), 最差 O(n**2),辅助空间 O(1)void BubbleSort(vector &nums){    int n = nums.size();    if (n==0) return;    for (int i=0;i nums[j+1])            {                // swap(nums[j], nums[j+1]);                int temp = nums[j];                nums[j] = nums[j+1];                nums[j+1] = temp;            }        }    }}

2. 选择排序

2.1 基本思想

选择排序(Select Sort) 是直观的排序,通过确定一个 Key 最大或最小值,再从带排序的的数中找出最大或最小的交换到对应位置。再选择次之。双重循环时间复杂度为 O(n^2)

算法描述:

  1. 在一个长度为 N 的无序数组中,第一次遍历 n-1 个数找到最小的和第一个数交换。
  2. 第二次从下一个数开始遍历 n-2 个数,找到最小的数和第二个数交换。
  3. 重复以上操作直到第 n-1 次遍历最小的数和第 n-1 个数交换,排序完成。

2.2 图解

2.3 代码

/*    1. 在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。    2. 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。    3. 以此类推,直到所有元素均排序完毕。*/// 不稳定排序,平均 O(n**2),最好 O(n**2), 最差 O(n**2),辅助空间 O(1)void SelectSort(vector &nums){    int n = nums.size();    if (n==0) return;    for (int i=0;i nums[j]);            {                idx = j;            }        }        if (idx !=i)        {            int temp = nums[idx];            nums[idx] = nums[i];            nums[i] = temp;        }    }}

3. 插入排序(重要)

3.1 基本思想

将一个数插入一个已经排好序的数据中。

  1. 第一次循环时,从第2个数开始处理。我们将第1个数作为已经排好序的数据:当第2个数 > 第1个数时,将第2个数放在第1个数后面一个位置;否则,将第2个数放在第1个数前面。此时,前两个数形成了一个有序的数据。
  2. 第二次循环时,我们处理第3个数。此时,前两个数形成了一个有序的数据:首先比较第3个数和第2个数,当第3个数 > 第2个数时,将第3个数放在第2个数后面一个位置并结束此次循环;否则,再和第1个数比较。如果第3个数 > 第1个数,则将第3个数插入第1个数和第2个数中间;否则,第3个数 < 第1个数,则将第3个数放在第1个数前面。此时,前三个数形成了一个有序的数据。
  3. 后续的数据同理处理,直至结束。

3.2 图解

3.3 代码

/*   直接插入排序基本思想是每一步将一个待排序的记录,插入到前面已经排好序的有序序列中去,直到插完所有元素为止。   1. 从第一个元素开始,该元素可以认为已经被排序   2. 取出下一个元素,在已经排序的元素序列中从后向前扫描   3. 如果被扫描的元素(已排序)大于新元素,将该元素后移一位   4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置   5. 将新元素插入到该位置后   6. 重复步骤2~5*/// 稳定排序,平均 O(n**2),最好 O(n), 最差 O(n**2),辅助空间 O(1)void InsertSort(vector &nums){    int n = nums.size();    if (n==0) return;    // 从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的    for (int i=1;i=0) && (temp < nums[j])          {                nums[j+1] = nums[j];                j--;          }          nums[j+1] = temp;    }}

另外小编还整理了一些各大知名企业BAT精选面试题、需要的朋友可以后台私信【面试题】获取

4. 归并排序(重要)

4.1 基本思想

归并排序的主要思想是分治法。主要过程是:

  1. 将n个元素从中间切开,分成两部分。(左边可能比右边多1个数)
  2. 将步骤1分成的两部分,再分别进行递归分解。直到所有部分的元素个数都为1。
  3. 从最底层开始逐步合并两个排好序的数列。

4.2 图解

4.3 代码

/*   将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序是一种稳定的排序方法。   1、确定数组的大小,以及输入数组中的元素值;2、将输入的数组进行分组归并;3、将整个数组分成左右两个数组,左右两个数组再向下分,直至子数组的元素少于2个时,子数组将停止分割;4、当左右子数组不能再分割,也是都是一个元素时,比较他们的大小,进行排序合并;5、再排序合并上一级子数组为两个元素的数组,接着再排序合并上一级子数组为四个元素的数组;直至到排序合并刚开始的两个子数组,最后成为拍好序的数组;*/// 稳定排序,平均 O(nlogn),最好 O(nlogn), 最差 O(nlogn),辅助空间 O(n)void merge(int array[],int first,int last){    int temp[last+1];    int mid=(first+last)/2;    int i=0; //临时数组指针    int l=first;//左序列指针    int r=mid+1;//右序列指针    while(l<=mid&&r<=last)//sort the ele of the left array and the right array    {        if(array[l]

5. 希尔排序

5.1 基本思想

希尔排序,也被称为递减增量排序,是简单插入排序的一种改进版本。

  • 在插入排序中,如果待排序列中的某个元素,距离有序数列中待插入位置非常远,就需要比较很多次才可以到达插入位置,这是因为待插入元素局部非常无序,比如说[2, 3, 4, 5, 6, 7, 8, 1, ...],我们要插入1,就必须将1和前面的2-8每个值都比较一下,就是因为1附近非常无序,想象一下,如果待插入元素附近比较有序,那么在进行插入排序的时候就只需要比较非常少的几次就可以插入到正确位置。
  • 希尔排序就是先把整个序列排得相对比较有序,再进行插入排序的时候,需要比较的次数就会变得很少。
  • 插入排序的增量(间隔)为1,希尔排序相当于将这个间隔从最大为数组长度的一半一直降到1,这一点在程序中体现的很清楚。当间隔很大时,比较的次数也会很少,在进行了几次大间隔的插入排序后,序列已经部分有序,这样再进行小间隔的插入排序也自然会比较很少的次数。
  • 希尔排序就是将处在相同间隔的元素提取出来单独进行插入排序,然后逐步将间隔减小到1的过程。

5.2 图解

5.3 代码

/*   数组列在一个表中并对列分别进行插入排序,重复这过程,不过每次用更长的列(步长更长了,列数更少了)来进行。*/// 不稳定排序,平均 O(nlogn)-O(n^2),最好 O(nlogn), 最差 O(n**2),辅助空间 O(1)void ShellSort(int a[],size_t n){    int i,j,k,group;    for (group = n/2; group > 0; group /= 2)//增量序列为n/2,n/4....直到1    {        for (i = 0; i < group; ++i)        {            for (j = i+group; j < n; j += group)            {                //对每个分组进行插入排序                if (a[j - group] > a[j])                {                    int temp = a[j];                    k = j - group;                    while (k>=0 && a[k]>temp)                    {                        a[k+group] = a[k];                        k -= group;                    }                    a[k] = temp;                }            }        }    }}

6. 快速排序(重要)

6.1 基本思想

快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

主要过程:

  1. 在待排序的元素任取一个元素作为基准(通常选第一个元素,称为基准元素)
  2. 将待排序的元素进行分块,比基准元素大的元素移动到基准元素的右侧,比基准元素小的移动到作左侧,从而一趟排序过程,就可以锁定基准元素的最终位置
  3. 对左右两个分块重复以上步骤直到所有元素都是有序的(递归过程)

6.2 图解

6.3 代码

/*    1. 从数列中挑出一个元素作为基准数。    2. 重新排序数列,将比基准数大的放到右边,小于或等于它的数都放到左边。    3. 再对左右区间递归执行第二步,直至各区间只有一个数。*/// 不稳定排序,平均 O(nlogn),最好 O(nlogn), 最差 O(n**2),辅助空间 O(logn)int Paritition (int A[], int low, int high) {    int pivot = A[low];    while (low < high)     {        while (low < high && A[high] >= pivot)         {            --high;        }        A[low] = A[high];        while (low < high && A[low] <= pivot)         {            ++low;        }        A[high] = A[low];    }    A[low] = pivot;    return low;}void QuickSort(int A[], int low, int high) //快排母函数{    if (low < high)     {        int pivot = Paritition1(A, low, high);        QuickSort(A, low, pivot - 1);        QuickSort(A, pivot + 1, high);    }}

精简版

void QuickSort(vector &nums, int low, int high){    if(low < high)    {        int l = low, r = high, pivot = nums[low];        while(l=pivot) // 从右向左找第一个小于基准的数            {                r--;            }            nums[l] = nums[r];            while(l

7. 对排序(重要)

7.1 基本思想

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树

  • 完全二叉树:除了最后一层之外的其他每一层都被完全填充,每一层从左到右的填充数据,不能空缺
  • 大根堆:任意一个节点的值均大于等于它的左右孩子的值,位于堆顶的节点值最大
  • 小根堆:任意一个节点的值均小于等于它的左右孩子的值,位于堆顶的节点值最小

堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了

  1. 将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
  2. 将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
  3. 重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。

7.2 图解

7.3 代码

/*堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了1.将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;2.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;3.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。*/// 不稳定排序,平均 O(nlogn),最好 O(nlogn), 最差 O(n**2),辅助空间 O(1)void adjustHeap(int nums[],int i,int length){    int temp = arr[i];//先取出当前元素i    for(int k=i*2+1;k=0;i--)    {        //从第一个非叶子结点从下至上,从右至左调整结构        adjustHeap(nums,i,len);    }    //2.调整堆结构+交换堆顶元素与末尾元素    for(int j=len-1;j>0;j--)    {        swap(nums[0],nums[j]);//将堆顶元素(最大值)与末尾元素进行交换,将最大值交换到数组的最后位置保存        adjustHeap(nums,0,j);//重新对堆进行调整    }}

9个元素换6次达到排序序列_面试题精选(排序算法类)c/c++版 上篇相关推荐

  1. 9个元素换6次达到排序序列_十大算法排序(Sorting Algorithm) Study notes

    (自己手打的python实现代码以及整理的各路大神总结的知识点) 自用学习笔记,由于基于北美cs学习,文章大量中英混杂(谨慎食用) 十大排序算法: 插入排序 1)Insertion Sort 简单插入 ...

  2. 9个元素换6次达到排序序列_原创系列 |冒泡排序提升为快速排序,都发生了什么?...

    「Python与算法社区」 第 310 篇原创 " 1 你会学到什么? " 彻底弄明白常用的排序算法的基本思想,算法的时间和空间复杂度,以及如何选择这些排序算法,确定要解决的问题的 ...

  3. 9个元素换6次达到排序序列_程序员必须掌握的:10大排序算法梳理已整理好

    从数组中选择最小元素,将它与数组的第一个元素交换位置.再从数组剩下的元素中选择出最小的元素,将它与数组的第二个元素交换位置.不断进行这样的操作,直到将整个数组排序. 动态过程 算法原理参考:图解选择排 ...

  4. 9个元素换6次达到排序序列_排序总结:二大种,六小种排序方式

    0.各种排序性能介绍 一.非线性时间比较排序 1.交换排序 1.1.冒泡排序 1.2.快速排序 2.插入排序 2.1.简单插入排序 2.2.希尔排序 3.选择排序 3.1.简单选择排序 3.2.堆排序 ...

  5. 9个元素换6次达到排序序列_(算法四)高级排序(快速排序)

    1.快速排序 快速排序是对冒泡排序的一种改进.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速 ...

  6. 9个元素换6次达到排序序列_全面讲解十大经典排序算法(Python实现)

    作者 | hustcc 链接 | https://github.com/hustcc/JS-Sorting-Algorith 排序算法是<数据结构与算法>中最基本的算法之一.排序算法可以分 ...

  7. 希尔排序是一种稳定的排序算法_十大经典排序算法——希尔排序

    vs code ppt c++/java 目录 1.1.排序分类 1.2.排序的定义: 对一序列对象根据某个关键字进行排序. 1.3.术语说明 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的 ...

  8. java面试排序都考哪几种排序_java算法面试题:排序都有哪几种方法?

    一.冒泡排序 [java] view plain copy package sort.bubble; import java.util.Random; /** * 依次比较相邻的两个数,将小数放在前面 ...

  9. java数字排序方法_常见的数据排序方法

    排序,顾名思义,就是将一组无序的数据按照指定的顺序(一般是从大到小或从小到大)进行排列的过程.不管是在Java还是在JavaScript.PHP.C/C++等编程语言中,对数组(或集合)进行排序都是程 ...

最新文章

  1. es6学习---.babelrc文件
  2. 第二届Byte Cup来袭,赢得2万美元奖金,登上字节跳动面试直通车
  3. python继承和多态_Python 简明教程 --- 21,Python 继承与多态
  4. Head First设计模式读书笔记四 简单工厂 工厂模式 抽象工厂模式
  5. LeetCode:62. 不同路径(python、c++)
  6. Entity Framework 4.0 FK Properties FK Associations
  7. 《电子元器件的可靠性》——3.7节电子元器件失效率鉴定试验
  8. 计算机课初中文化的学生招,计算机应用 教学计划
  9. C语言冒泡排序(从小到大排序)
  10. python下载电影包_我是如何使用python控制迅雷自动下载电影的?
  11. 元宇宙通证- 九、IT/ICT发展史全景长图
  12. Python系统学习第二十四课
  13. paoding 中文分词学习
  14. SMM框架简单用户增删改查
  15. 低代码技巧:甘特图制作步骤
  16. h5后缀文件python处理
  17. 计算机的存储器(详解)
  18. Java 面试题及答案
  19. 凹凸手游服务器维护中是什么意思,凹凸世界手游测试炸服补偿公告介绍 开服进不去有什么补偿[多图]...
  20. 【MVC-自定义过滤器】

热门文章

  1. VSTS 下的敏捷开发模板
  2. Android data分区格式F2FS改为EXT4
  3. 如何在 Ubuntu 中安装和删除软件
  4. 网页广告拦截神器 -- Adblock Plus
  5. Python爬取你好李焕英豆瓣短评生成词云
  6. Android10加入APEX目的
  7. Android Studio 2.3报错: Error:Cause: buildToolsVersion is not specified解决
  8. daemon守护进程初识
  9. ffmpeg (四):ffmpeg, ffplay, ffprobe用法
  10. Clojure 学习入门(10)- httpkit