【算法】--- 几分钟带你走进排序算法大门(上)

简介: 算法学习第一弹——排序算法

🌟一、常见的排序算法:


🌟二、直接插入排序排序:


📒2.1 基本思想:


直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。实际中我们玩扑克牌时,就用了插入排序的思想

📒2.2 代码:


#include<stdio.h>
void PrintArray(int* a, int n)
{
  for (int i = 0; i < n; i++)
  {
    printf("%d ", a[i]);
  }
  printf("\n");
}
void InsertSort(int* a,int n)
{
//[0, end]有序end+1位置的值插入[0, end]...让[0, end+1]有序
  for (int i = 0; i < n - 1; i++)
  {
    int end = i;
    int tmp = a[end + 1];
    while (end >= 0)
    {
      if (a[end] > tmp)
      {
        a[end + 1] = a[end];
        end--;
      }
      else
      {
        break;
      }
    }
    a[end+1] = tmp;
  }
}
void TestInsertSoret()
{
  int a[] = { 3,5,2,7,1,4,9,8,0,6 };
  int sz = sizeof(a) / sizeof(a[0]);
  InsertSort(a, sz);
  PrintArray(a, sz);
}
int main()
{
  TestInsertSoret();
  return 0;
}

📒2.3 时间复杂度:O(N^2)


逆序的情况下最坏(每个数字都需要移动)等差数列:1+2+3+… …+(n-1)

顺序有序的情况下最好:O(N)

📒2.4 流程图详解:


🌟三、希尔排序(缩小增量排序):


📒3.1 基本思想:


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

📒3.2 希尔排序思想图:


📒3.3 希尔排序画图详解:


📒3.4 代码:


#include<stdio.h>
void PrintArray(int* a, int n)
{
  for (int i = 0; i < n; i++)
  {
    printf("%d ", a[i]);
  }
  printf("\n");
}
void ShellSort(int* a, int n)
{
  int gap = n;
  while (gap > 1)
  {
    gap /= 2;
    //gap = gap / 3 + 1;这种也可以保证最后一次gap=1进行直接插入排序
    //把间隔为gap的多组数据同时排
    //gap > 1时都是预排序接近有序
    //gap == 1时就是直接插入排序有序
    for (int i = 0; i < n - gap; i++)
    {
      int end = i;
      int tmp = a[end + gap];
      while (end >= 0)
      {
        if (a[end] > tmp)
        {
          a[end + gap] = a[end];
          end -= gap;
        }
        else
        {
          break;
        }
      }
      a[end + gap] = tmp;
    }
  }
}
void TestInsertSoret()
{
  int a[] = { 3,5,2,7,1,4,9,8,0,6 };
  int sz = sizeof(a) / sizeof(a[0]);
  ShellSort(a, sz);
  PrintArray(a, sz);
}
int main()
{
  TestInsertSoret();
  return 0;
}

📒3.5 希尔排序画图详解:


📒3.6 希尔排序总结:


希尔排序是对直接插入排序的优化。

当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。

希尔排序的时间复杂度不好计算,需要进行推导,推导出来平均时间复杂度:O(N^1.3—N42)

稳定性:不稳定

多且间隔为gap的预排序,gap由大变小

gap越大,大的数可以越快的到后面,小的数可以越快的到前面

gap越大,预排完越不接近有序,: gap越小,越接近有序

gap ==1时就是直接插入排序

📒3.7 希尔排序时间复杂度:O(logN*N)


while(gap>1){gap /= 2… …}外边这个循环跑logN

里面的for循环:

gap很大时,下面预排序时间复杂度O(N)

gap很小时.数组已经很接近有序了…这时差不多也是O(N)

🌟四、希尔排序和直接插入排序性能的比较:


#include<stdio.h>
#include<stdlib.h>
#include<time.h>
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 (a[end] > tmp)
      {
        a[end + 1] = a[end];
        end--;
      }
      else
      {
        break;
      }
    }
    a[end + 1] = tmp;
  }
}
void ShellSort(int* a, int n)
{
  int gap = n;
  while (gap > 1)
  {
    gap /= 2;
    for (int i = 0; i < n - gap; i++)
    {
      int end = i;
      int tmp = a[end + gap];
      while (end >= 0)
      {
        if (a[end] > tmp)
        {
          a[end + gap] = a[end];
          end -= gap;
        }
        else
        {
          break;
        }
      }
      a[end + gap] = tmp;
    }
  }
}
void TestOP()
{
  srand(time(0));
  const int N = 1000000;
  int* a1 = (int*)malloc(sizeof(int) * N);
  int* a2 = (int*)malloc(sizeof(int) * N);
  int* a3 = (int*)malloc(sizeof(int) * N);
  int* a4 = (int*)malloc(sizeof(int) * N);
  int* a5 = (int*)malloc(sizeof(int) * N);
  int* a6 = (int*)malloc(sizeof(int) * N);
  for (int i = 0; i < N; i++)
  {
    a1[i] = rand();
    a2[i] = a1[i];
    a3[i] = a1[i];
    a4[i] = a1[i];
    a5[i] = a1[i];
    a6[i] = a1[i];
  }
  int begin1 = clock();
  InsertSort(a1,N);
  int end1 = clock();
  int begin2 = clock();
  ShellSort(a2,N);
  int end2 = clock();
  printf("InsertSort:%d\n", end1 - begin1);
  printf("ShellSort:%d\n", end2 - begin2);
  free(a1);
  free(a2);
  free(a3);
  free(a4);
  free(a5);
  free(a6);
}
int main()
{
  TestOP();
  return 0;
}

🌟总结:


本章内容是对排序算法中的部分排序做了一个解析总结。

相关文章
|
7月前
|
搜索推荐 算法 Shell
【算法tips】面试官:说说常见的排序算法。—— 巧记十种排序算法名称
【算法tips】面试官:说说常见的排序算法。—— 巧记十种排序算法名称
484 2
|
7月前
|
JavaScript 算法 前端开发
【前端也要学算法系列】经典排序算法JS实现 —— 冒泡排序
【前端也要学算法系列】经典排序算法JS实现 —— 冒泡排序
437 0
|
8月前
|
算法 搜索推荐 程序员
初阶算法(1):通过简单的排序算法来认识时间复杂度
初阶算法(1):通过简单的排序算法来认识时间复杂度
|
5月前
|
存储 算法 搜索推荐
【算法训练-排序算法 三】【排序应用】合并区间
【算法训练-排序算法 三】【排序应用】合并区间
49 0
|
3月前
|
存储 分布式计算 搜索推荐
【数据结构排序算法篇】----对十大经典算法的总结
【数据结构排序算法篇】----对十大经典算法的总结
35 0
|
4月前
|
机器学习/深度学习 存储 人工智能
算法05-排序算法
算法05-排序算法
|
4月前
|
搜索推荐 JavaScript 前端开发
用openAI写个js的排序算法(快速排序算法)
用openAI写个js的排序算法(快速排序算法)
19 0
|
4月前
|
算法 搜索推荐 Java
数据结构与算法面试:基于比较的排序算法时间复杂度最坏情况下是 O(nlogn),请问有没有更快的算法?(提示:计数排序、基数排序)
数据结构与算法面试:基于比较的排序算法时间复杂度最坏情况下是 O(nlogn),请问有没有更快的算法?(提示:计数排序、基数排序)
21 0
|
9月前
|
搜索推荐 算法
图解算法--排序算法
1.冒泡排序算法 2.选择排序算法 3.插入排序算法 4.希尔排序算法 5.归并排序算法 6.快速排序算法
28874 6
|
10月前
|
算法 搜索推荐 测试技术
【算法】十大排序算法以及具体用例算法题
【算法】十大排序算法以及具体用例算法题
371 0