数据结构从入门到精通(第四篇) :排序的入门(插入排序,希尔排序,选择排序,冒泡排序)

简介: 数据结构从入门到精通(第四篇) :排序的入门(插入排序,希尔排序,选择排序,冒泡排序)

排序的概念及其运用

排序的概念

排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。


稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次

序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排

序算法是稳定的;否则称为不稳定的。 内部排序:数据元素全部放在内存中的排序。


外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。


排序运用

高校排名:

image.png

接下来,我会一一介绍几种常见的排序算法


插入排序

直接插入排序

直接插入排序是一种简单的插入排序法


基本思想: 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列


代码的实现

//直接插入排序
void InsertSort(int* a, int n)
{
  assert(a);//传入数组不为空指针
  int i;
  for (i = 0; i < n - 1; i++)
  {
  int end = i;
  int x = a[end + 1];
  while (end >= 0)
  {
    //升序
    if (a[end] >x)
    {
    a[end + 1] = a[end];
    end--;
    }
    else
    {
    break;
    }
  }
  a[end + 1] = x;
  }
}


希尔排序


解析

希尔排序在直接排序之前,进行预排列,将某些极端数据更快的排列到数列前面,构成一个接近排列好的序列,最后再进行一次直接插入排序


预排列的原理也是插入排列,只不过这里的将数组分成了gap组,分别对每一个小组进行插入排序

// 希尔排序
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 x = a[end + gap];
    while (end >= 0)
    {
    if (a[end] > x)
    {
      a[end + gap] = a[end];
      end-=gap;
    }
    else
      break;
    }
    a[end + gap] = x;
  }
  }
}


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


选择排序

直接选择排序

解析

每一次遍历待排序的数据元素从中选出最小(或最大)的一个元素,存放在序列的起始(或者末尾)位置,直到全部待排序的数据元素排完


代码的实现

// 选择排序
void SelectSort(int* a, int n)
{
  int begin = 0, end = n - 1;//记录下标
  while (begin < end)
  {
  int mini = begin;
  for (int i = begin; i <= end; i++)
  {
    //遍历找到最小数据并记录下标
    if (a[i] < a[mini])
    mini = i;
  }
  Swap(&a[begin], &a[mini]);//交换
  begin++;//缩小范围
  }
}


总结


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

空间复杂度:O(1)

稳定性:不稳定


不推荐使用


堆排序

堆排序是指利用堆(数据结构)进行选择数据的一种排序算法


基础思想:


原则:

先将原数组建成堆,需要注意的是排升序要建大堆,排降序建小堆

注:以大堆为例


建堆:

一个根节点与子节点数据如果不符合大堆结构,那么则对根节点数据进行向下调整,而向下调整的前提是左右子树也符合大堆结构,所以从堆尾数据的根节点位置开始向下调整建大堆


排序:

大堆堆顶数据一定是待排数据中最大的,将堆顶数据与堆尾数据交换,交换后将除堆尾数据看成新堆,对现堆顶数据进行向下调整成大堆,以此循环直至排列完毕


向下调整:

找到子节点中的较大数据节点比较,如果父节点数据比大子节点小则交换,直到不符合则停止向下交换,此时再次构成了一个大堆结构.


代码的实现

void Adjustdown(int* a, int n,int parent)
{
  int child = parent * 2 + 1;
  while (child < n)
  {
  //找到数据大的子结点
  if (child + 1 < n && a[child + 1] > a[child])
  {
    child++;
  }
  //父节点数据小于子节点就交换
  if (a[parent] < a[child])
  {
    Swap(&a[parent], &a[child]);
    //更新下标
    parent = child;
    child = parent * 2 + 1;
  }
  else//否则向下调整完毕
    break;
  }
}
// 堆排序(升序)建大堆
void HeapSort(int* a, int n)
{
  int i;
  //建大堆
  for (i = (n - 1 - 1) / 2; i >= 0; i--)
  {
  Adjustdown(a, n, i);
  }
  //交换调整
  for (i = n - 1; i >= 0; i--)
  {
  Swap(&a[0], &a[i]);//与当前堆尾数据交换
  Adjustdown(a, i, 0);//对交换后堆顶数据进行向下调整
  }
}


总结:

堆排序使用堆来选数,效率就高了很多。

时间复杂度:O(N*logN)

空间复杂度:O(1)

稳定性:不稳定

交换排序之冒泡排序


冒泡排序


每次遍历数组,对相邻数据进行比较,不符合排序要求则交换


代码的实现

// 冒泡排序
void BubbleSort(int* a, int n)
{
  int i, j;
  for (i = 0; i < n - 1; i++)//趟数
  {
  for (j = 0; j < n - 1 - i; j++)//比较次数
  {
    if (a[j] > a[j + 1])//满足条件
    Swap(&a[j], &a[j + 1]);//交换
  }
  }
}


总结

排序的第一篇就讲到这里了,下一篇还会讲快速排序和归并排序,希望大家多多支持!!


相关文章
|
9月前
|
搜索推荐 算法 数据处理
【C++数据结构——内排序】希尔排序(头歌实践教学平台习题)【合集】
本文介绍了希尔排序算法的实现及相关知识。主要内容包括: - **任务描述**:实现希尔排序算法。 - **相关知识**: - 排序算法基础概念,如稳定性。 - 插入排序的基本思想和步骤。 - 间隔序列(增量序列)的概念及其在希尔排序中的应用。 - 算法的时间复杂度和空间复杂度分析。 - 代码实现技巧,如循环嵌套和索引计算。 - **测试说明**:提供了测试输入和输出示例,帮助验证代码正确性。 - **我的通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了代码运行的测试结果。 通过这些内容,读者可以全面了解希尔排序的原理和实现方法。
151 10
|
12月前
|
算法 搜索推荐 Shell
数据结构与算法学习十二:希尔排序、快速排序(递归、好理解)、归并排序(递归、难理解)
这篇文章介绍了希尔排序、快速排序和归并排序三种排序算法的基本概念、实现思路、代码实现及其测试结果。
302 1
|
12月前
|
算法 搜索推荐
数据结构与算法学习十一:冒泡排序、选择排序、插入排序
本文介绍了冒泡排序、选择排序和插入排序三种基础排序算法的原理、实现代码和测试结果。
350 0
数据结构与算法学习十一:冒泡排序、选择排序、插入排序
|
12月前
|
存储 应用服务中间件 nginx
Nginx入门 -- 基本数据结构中之ngx_str_t,ngx_array_t
Nginx入门 -- 基本数据结构中之ngx_str_t,ngx_array_t
212 1
|
12月前
|
存储 机器学习/深度学习 算法
探索数据结构:入门及复杂度的解锁
探索数据结构:入门及复杂度的解锁
|
搜索推荐
【数据结构常见七大排序(三)上】—交换排序篇【冒泡排序】And【快速排序】
【数据结构常见七大排序(三)上】—交换排序篇【冒泡排序】And【快速排序】
【数据结构常见七大排序(三)上】—交换排序篇【冒泡排序】And【快速排序】
|
12月前
|
存储 缓存 应用服务中间件
Nginx入门 -- 基本数据结构中之ngx_hash_t
Nginx入门 -- 基本数据结构中之ngx_hash_t
100 0
|
12月前
|
存储 缓存 应用服务中间件
Nginx入门 -- 基本数据结构中之ngx_list_t,ngx_queue_t
Nginx入门 -- 基本数据结构中之ngx_list_t,ngx_queue_t
211 0
|
存储 算法 搜索推荐
【初阶数据结构篇】冒泡排序和快速排序(中篇)
与直接插入排序法相比,比较次数一致,但冒泡排序的交换需要执行三次,而直接插入排序因为使用了tmp临时变量存储要插入的数据,只用执行一次,所以直接插入排序法效率明显更高。
77 1
|
应用服务中间件 nginx C语言
Nginx入门 -- 基本数据结构中之ngx_str_t,ngx_array_t
这两种数据结构是Nginx自定义数据类型的例子,它们证明了Nginx设计者在构建一个为高并发和高性能优化的web服务器时的精确和高效。理解这些数据结构是深入学习Nginx内部机制的基础,同时也是扩展和开发Nginx模块不可或缺的一部分知识。
113 1