
我的个人主页 {\large \mathsf{{\color{Red} 我的个人主页} } } 我的个人主页
我的专栏: \mathcal{{\color{Green} 我的专栏:} } 我的专栏: 《精选文章》《算法》《每日一道编程题》《高精度算法》
目录
文章概览

前言
面对庞大的数据,我们有可能需要排序,而如何排序以及选择更优的排序是一个非常棘手的问题。所以今天,我来给大家讲解冒泡排序、选择排序、插入排序、快速排序。
1、冒泡排序
冒泡排序的介绍
冒泡排序(Bubble Sort)的步骤如下:
- 比较相邻的元素。如果第一个比第二个大,就进行交换。
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在最后的元素将会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个元素。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
动态演示如下:

冒泡排序的优缺点
优点:
- 容易理解
- 十分稳定
- 空间复杂度为 O ( 1 ) O(1) O(1)
缺点就一个,但是是非常重要的:
时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)
这也太慢了吧
代码
for(int i=n-1; i>=1; i--)
{
for(int j=1; j<=i; j++)
{
if(a[j]>a[j+1])
{
swap(a[j],a[j+1]);
}
}
}
来试一下
输入:3 5 2 1 9 8
输出:1 2 3 5 8 9
完美!

优化
我们发现,像 “1 2 3 4 6 5” 这样的数列排一次就可以了,更何况是 “1 2 3 4 5 6” 这种一开始就排好序的数列,那么我们可以在排序的同时检查是否已经排行数列,代码如下:
for(int i=n-1; i>=1; i--)
{
bool flag=false;
for(int j=1; j<=i; j++)
{
if(a[j]>a[j+1])
{
swap(a[j],a[j+1]);
flag=true;
}
}
if(!flag)
{
break;
}
}
2、 选择排序
选择排序的介绍
选择排序(Selection Sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。
动态演示如下:

选择排序的优缺点
优点:
- 空间复杂度为 O ( 1 ) O(1) O(1)
- 简单直观
缺点:
- 时间复杂度为 O ( N 2 ) O(N^2) O(N2)
- 不稳定
代码
for(int i=1; i<=n-1; i++)
{
int MIN_I=i,MIN=a[i];
for(int j=i+1; j<=n; j++)
{
if(a[j]<MIN)
{
MIN_I=i;
MIN=a[j];
}
}
swap(a[i],a[MIN_I]);
}
来试一下
输入:3 5 2 1 9 8
输出:1 2 3 5 8 9
完美!

3、插入排序
插入排序的介绍
插入排序(Insertion sort)的工作方式像排序一手扑克牌。开始时,我们的左手为空并且桌子上的牌面向下。然后,我们每次从桌子上拿走一张牌并将它插入左手中正确的位置。为了找到一张牌的正确位置,我们从右到左将它与已在手中的每张牌进行比较。拿在左手上的牌总是排序好的,原来这些牌是桌子上牌堆中顶部的牌。
动态演示如下:

插入排序的优缺点
优点:
- 空间复杂度为 O ( 1 ) O(1) O(1)
- 直观
- 稳定
缺点就一个,但是是非常重要的:
时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)
这也太慢了吧
代码
for(int i=2; i<=n; i++)
{
int temp=s[i];
int j;
for(j=i-1; j>=0 && temp<=s[j]; j--)
{
s[j+1]=s[j];
}
s[j+1]=temp;
}
来试一下
输入:3 5 2 1 9 8
输出:1 2 3 5 8 9
完美!

优化
for(int i=2; i<=n; i++)
{
int temp=a[i],low=0,high=i-1;
while(low<=high)
{
int mid=(high+low)/2;
if(a[mid]>temp)
{
high=mid-1;
}
else
{
low=mid+1;
}
}
for(int j=i-1; j>=low; j--)
{
a[j+1]=a[j];
}
a[low]=temp;
}
4、快速排序
快速排序的介绍
快速排序(Quicksort)采用的是分治思想,即在一个无序的序列中选取一个任意的基准元素pivot,利用pivot将待排序的序列分成两部分,前面部分元素均小于或等于基准元素,后面部分均大于或等于基准元素,然后采用递归的方法分别对前后两部分重复上述操作,直到将无序序列排列成有序序列。
动态演示如下:

快速排序的优缺点
优点:
- 时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)
- 空间复杂度为 O ( l o g n ) O(logn) O(logn)
缺点就一个:
不稳定
代码
void quicksort(int left,int right,int a[])
{
int i,j,t,temp;
if(left>right) return;
temp=a[left];
i=left;
j=right;
while(i!=j)
{
while(a[j]>=temp && i<j) j--;
while(a[i]<=temp && i<j) i++;
if(i<j) swap(a[i],a[j]);
}
a[left]=a[i];
a[i]=temp;
quicksort(left,i-1,a);
quicksort(i+1,right,a);
}
来试一下
输入:3 5 2 1 9 8
输出:1 2 3 5 8 9
完美!

194



被折叠的 条评论
为什么被折叠?



