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

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

🌟一、常见的排序算法:


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


📒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;
}

🌟总结:


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

相关文章
|
搜索推荐 算法 Shell
【算法tips】面试官:说说常见的排序算法。—— 巧记十种排序算法名称
【算法tips】面试官:说说常见的排序算法。—— 巧记十种排序算法名称
544 2
|
2月前
|
机器学习/深度学习 存储 缓存
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
45 1
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
|
6月前
|
算法 搜索推荐 测试技术
【调度算法】快速非支配排序算法
【调度算法】快速非支配排序算法
59 3
|
2月前
|
搜索推荐 算法
数据结构与算法学习十四:常用排序算法总结和对比
关于常用排序算法的总结和对比,包括稳定性、内排序、外排序、时间复杂度和空间复杂度等术语的解释。
33 0
数据结构与算法学习十四:常用排序算法总结和对比
|
2月前
|
机器学习/深度学习 搜索推荐 算法
探索数据结构:初入算法之经典排序算法
探索数据结构:初入算法之经典排序算法
|
6月前
|
搜索推荐 算法 数据挖掘
十大排序算法详解-上篇:比较排序算法【python 动态图解】
十大排序算法详解-上篇:比较排序算法【python 动态图解】
|
6月前
|
存储 算法 搜索推荐
【数据结构和算法】--- 基于c语言排序算法的实现(2)
【数据结构和算法】--- 基于c语言排序算法的实现(2)
40 0
|
6月前
|
搜索推荐 算法 大数据
​【数据结构与算法】冒泡排序:简单易懂的排序算法解析
​【数据结构与算法】冒泡排序:简单易懂的排序算法解析
|
6月前
|
搜索推荐 算法 C语言
【数据结构和算法】--- 基于c语言排序算法的实现(1)
【数据结构和算法】--- 基于c语言排序算法的实现(1)
51 0
|
7月前
|
存储 算法 搜索推荐
黑马c++ STL常用算法 笔记(3) 排序算法
黑马c++ STL常用算法 笔记(3) 排序算法