手撕各种排序(上)

简介: 手撕各种排序

> 作者简介:დ旧言~,目前大一,现在学习Java,c,c++,Python等

> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:掌握每种排序的方法,理解每种排序利弊和复杂度。

> 毒鸡汤:船停在码头是最安全的,但那不是造船的目的;人呆在家里是最舒服的,但那不是人生的意义。最美好的生活方式,莫过于和一群志同道合的人奔跑在理想的路上!

> 望小伙伴们点赞👍收藏✨加关注哟💕💕

🌟前言

       谈起排序这个事情,大家都是耳熟能详的事了,从我们认识的斗地主,每一复牌都是按照从小到大的顺序排序的,如图:


      排序的目的是为了让我们很好的管理,使无序的事情变成有序,当然排序的方法有很多,如由大到小,由大到小.....。而面对大量数据就需要排序。在数据结构中我们发明了多种排序,如我们最早认识的冒泡排序,本篇博客让大家对多种排序有一个很好的认知,闲话少谈。

主体  

咱们就掌握八种就行啦


🌙冒泡排序

这里博主在C语言刷题训练专栏中讲到过冒泡排序,咱们再回顾回顾


这里我们以接口的形式写代码,那咱们上代码咯


//冒泡排序测试
void BubbleSort(int* a, int n)
{
  for (int i = 0; i < n - 1; i++)
  {
    int exchange = 0;
    for (int j = 1; j < n - i; j++)
    {
      if (a[i - 1] > a[i])
      {
        //这里是一个交换函数
        Swap(&a[i - 1], &a[i]);
        exchange = 1;
      }
    }
    //这里进行一趟有序时,直接跳出循环
    if (exchange == 0)
    {
      break;
    }
  }
}

注意事项:

💦1.我们知道当给的数据有序时,就不再需要进行循环了,直接跳出循环(exchange作用)。

💦2. 第二个循环中  j < n - i  不能搞错。

时间复杂度:O(N²)

空间复杂度:O(1)

稳定性:稳定

复杂性:简单

🌙直接插入排序

     直接插入排序是一种简单的插入排序法,其基本思想是: 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 ,就好像我们斗地主拿牌插入相似。


咱们看看一个动态的插入动作。


这里我们以接口的形式写代码,那咱们上代码咯


//插入排序
void InsertSort(int* a, int n)
{
  for (int i = 0; i < n - 1; i++)
  {
    int end = i;
    int tmp = a[end + 1];
    //一个元素进行插入
    while (end >= 0)
    {
      if (tmp < a[end])
      {
        a[end + 1] = a[end];
      }
      else
      {
        break;
      }
      --end;
    }
    //最后把插入的元素赋值回去
    a[end + 1] = tmp;
  }
}

注意事项:

💦1.我们先进行第end个元素移动,再进行n个元素进行移动。

💦2. 最后需要a[end + 1] = tmp赋值

时间复杂度:O(N²)

空间复杂度:O(1)

稳定性:稳定

复杂性:简单

🌙希尔排序

      希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。咱们看看下面的图解:



在看看一个动态的图解:


 这里我们以接口的形式写代码,那咱们上代码咯

//希尔排序测试
void ShellSort(int* a, int n)
{
  int gap = n;
  while (gap > 1)
  {
    //间隔gap的元素进行排序
    gap = gap / 3 + 1;
    //本质上是插入排序
    for (int i = 0; i < n - gap; ++i)
    {
      int end = i;
      int tmp = a[end + gap];
      //一个元素进行插入
      while (end >= 0)
      {
        if (tmp < a[end])
        {
          a[end + gap] = a[end];
          end = end - gap;
        }
        else
        {
          break;
        }
      }
      //最后把插入的元素赋值回去
      a[end + gap] = tmp;
    }
  }
}

注意事项:

💦1.首先先嵌套一个插入排序,再把分组的元素进行交换。

💦2. gap = gap / 3 + 1这个不要忘记。

时间复杂度:O(N¹·²³)

空间复杂度:O(1)

稳定性:不稳定

复杂性:复杂


手撕各种排序(中):https://developer.aliyun.com/article/1389401

目录
相关文章
|
6天前
|
算法 搜索推荐 索引
手撕各种排序(下)
手撕各种排序(下)
40 0
|
6天前
|
搜索推荐
手撕各种排序(中)
手撕各种排序(中)
49 0
|
8月前
|
算法 搜索推荐
【数据结构与算法篇】手撕八大排序算法之交换排序
【数据结构与算法篇】手撕八大排序算法之交换排序
33 0
|
8月前
|
机器学习/深度学习 存储 算法
【数据结构与算法篇】 手撕八大排序算法之选择排序
【数据结构与算法篇】 手撕八大排序算法之选择排序
38 0
|
8月前
|
算法 程序员
手撕代码
手撕代码是什么
|
9月前
|
缓存 调度
手撕代码系列(四)
手撕代码系列(四)
|
9月前
|
搜索推荐 算法 Shell
手撕希尔排序
手撕希尔排序
53 0
|
10月前
|
存储
手撕二叉搜索树
手撕二叉搜索树
41 0
【手撕归并排序】
一、归并排序是什么? 归并排序是将一段区间分成若干个子问题,子问题再次分成子问题,这个是分治过程;最后分成的子问题只存在一个数时,就可以开始合并,合并的过程就是比较两个子问题的过程,合并完成后将合并的新数据拷贝到原数据即可。