一、排序运用场景
(1)排序概念:将一组杂乱无章的数据按照一定的规律(升序或降序)组织起来。
(2)运用场景:
(1)淘宝、支付宝、京东等购物平台的价格排序、质量排序、商家服务态度排序等…
(2)全国高校排名排序、院校专业排序…
二、常见排序算法
(1)排序算法分类
注:以下是排序算法的细节讲解!!!
【1】气泡的舞蹈
对于冒泡排序,相信大家都对其并不陌生。虽然其时间复杂度不好,一般不作为工程上的排序使用,但是其也有着排序初步认识的地位!
①冒泡排序(Bubble Sort):一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。
根据冒泡排序的特性,我们就可以使用代码来将其过程模拟出来!
void Swap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
void Print_Arr(int* arr, int size)
{
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
}
//排序->升序
void Bubble_Sort(int* arr, int size)
{
//假设初始状态的数组为有序
int flag = 1;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size-i-1; j++)
{
if (arr[j] > arr[j + 1])
{
Swap(arr[j], arr[j + 1]);
flag = 0;
}
}
if (flag == 1)
{
break;
}
}
}
这是实现的效果图:
代码解释:
1、对于初始化flag=1的解释:
2、对于在一次遍历过程中,进入if判断条件之后的对于flag=0的解释:
3、对于结束遍历条件的解释:
下面放一个冒泡排序的动图!
【2】希尔的节奏
注:在学习希尔之前,我们需要了解一些希尔排序的历史!
其实,希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。所以,我们在接触希尔排序之前,需要了解并熟悉应用直接插入排序的算法思路和代码实现!
(1)前奏:直接插入排序
以下是直接插入排序的动图!
从中我们可以看到:直接插入排序可以说成是将一条记录插入到已排好的有序表中,从而得到一个新的有序表。
以下是代码实现!
void Insert_Sort(int* arr, int size)
{
for (int i = 0; i < size-1; i++)
{
//定义已排序的最后一个数据下标为end
int end = i;
int tmp = arr[end + 1];
while (end>=0)
{
if (tmp < arr[end])
{
arr[end + 1] = arr[end];
end--;
}
else
{
break;
}
}
arr[end + 1] = tmp;
}
}
以下是终端结果:
代码的解释:
从直接插入排序算法我们可以很容易的得到其时间复杂度为O(N^2),其代码运行的效率并不好,有什么解决方法吗???
(2)高潮:希尔排序
①希尔排序定义:插入排序的一种,又称“缩小增量排序”。
②基本思想:相对于直接插入排序的对整个数组进行‘1’分组,希尔排序通常将数组先分成几个大数组,在这几个大数组中先进行直接插入排序,在对每个大数组进行排序,从而减少插入排序的时间复杂度!
③直接插入排序其实就是希尔排序增量为‘1’的特殊情况!
下面是其代码的实现:
void Shell_Sort(int* arr, int size)
{
//提供一个分组变量
int gap = size;
while (gap>1)
{
gap = gap / 3 + 1;
for (int i = 0; i < size - gap; i++)
{
//定义已排序的最后一个数据下标为end
int end = i;
int tmp = arr[end + gap];
while (end >= 0)
{
if (tmp < arr[end])
{
arr[end + gap] = arr[end];
end-=gap;
}
else
{
break;
}
}
arr[end + gap] = tmp;
}
}
}
以下是代码解释:
gap = gap / 3 + 1;
这串代码是将数组进行分组,将数组分成gap组,先将每组内部的数据排成有序的,最后当 gap=1 时即进行一次直接插入排序,即完成数组的排序!
这是终端结果:
因为希尔排序又被称作“减少增量排序”,所以其减少增量的方法也是各不相同的!下面是Sedgewick的增量序列:
④希尔排序的时间复杂度大概为:O(N^1.3).
【3】选择的艺术
①选择排序也因为其时间复杂度过高的原因,一般在实践中不作为使用,但在学习和深入了解排序算法仍然有其作用!
②算法思想:每一次从待排序的数组元素中选出最小的/最大的,存放在序列的起始位置/终止位置,直到所有数据排完为止!
③直接选择排序的动图:
代码实现:
void Select_Sort(int* arr, int size)
{
int begin = 0, end = size - 1;
while (begin<end)
{
//这里的maxi和mini都是指数组中数字的下标
int maxi = end, mini = begin;
for (int i = begin; i <= end; i++)
{
if (arr[i] < arr[mini]) {
mini = i;
}
if (arr[i] > arr[maxi])
{
maxi = i;
}
}
//防止当max和begin值相等时,出现多次错误交换!
if (maxi == begin)
{
maxi = mini;
}
Swap(arr[begin], arr[mini]);
Swap(arr[end], arr[maxi]);
begin++;
end--;
}
}
以下是终端结果:
本期结束!我们下期再见!!!