今天介绍一些排序算法,作为算法中最基础的部分,掌握各种排序算法以及指导各种排序算法的复杂度是有必要的。
插入排序
顾名思义,插入排序就是首先在待排序的数组中挑选出一个数,然后向前看,找到它所在的合适位置,将该位置后面的数都后移一次,再将选取的数插进去就行。其原理就跟咱们打扑克插牌是一样的。
以下面五个无序的数字为例:
2 3 1 5 4
第一次插入:2 3 1 5 4(3比2大,不用动)
第二次插入:1 2 3 5 4(将1插到第一位,2,3后移)
第三次插入:1 2 3 5 4(5前面没有比5大的,不动)
第四次插入:1 2 3 4 5(4插到第四位,5后移)
void charupaixu(int *a,int n)
{
for(int i=1;i<n;i++)
{
int x=a[i];
int j=i-1;
while(j>=0&&a[j]>x)
{
a[j+1]=a[j];
j--;
}
a[j+1]=x;
}
}
算法复杂度为O(N²)
冒泡排序
冒泡排序这个名字期的非常生动,相信你看完下面的解释就会明白它为什么叫这个名字。
冒泡排序与插入排序不同,插入排序是选取一个对象与多个对象进行比较,而冒泡排序是两个元素互相比较,例如给出一串无序数组:2 3 1 4 5。而我们想让数组从小到大排列,操作如下:
- 第一遍冒泡:我们想把最大的找到,并放到最后一位,那么应该是:
2 3 1 5 4(2与3比较,3比2大,不用动)
2 1 3 5 4(3与1比较,3大,交换位置)
2 1 3 5 4(3与5比较,5比3大,不动)
2 1 3 4 5(5与4比较,5比4大,交换位置)
经过第一遍过程我们可以清晰地看到最大的5已经被我们挪到最后一位了,所以我们接下来在排序就对前四个数进行冒泡即可 - 第二遍冒泡
1 2 3 4 5
过程就省略啦,就是对前四个数在进行一遍上面的操作,再往下就分别是前三个数,前两个数。。。
void maopaopaixu(int *a,int n)
{
int t;
for(int i=0;i<n-1;i++)
{
for(int j=0;j<n-i-1;j++)
{
if(a[j+1]<a[j])
{
t=a[j+1];
a[j+1]=a[j];
a[j]=t;
}
}
}
}
算法复杂度为O(N²)
选择排序
我还是爱把这种办法叫做打擂法,因为选择排序的排序过程中就像是在打擂台一样,挨个打一遍,直到剩下我们想要的最大(小)的数。
以从小到大排列为例,原理是先从其中找到最小的数,并且把最小的数放在第一位,在找到第二小的数,放倒第二位,以此类推。
例如给定一组无序数:2 3 1 5 4
第一次排序:1 3 2 5 4(找到最小的1,并将其与第一位2互换)
第二次排序:1 2 3 5 4(找到第二小的2,与第二位3互换)
第三次排序:1 2 3 5 4(第三小的3,正好在第三位,不动)
第四次排序:1 2 3 4 5(第四小的4,与第四位互换)
void xuanzepaixu(int *a,int n)
{
int s;
for(int i=0;i<n;i++)
{
int t=i;
for(int j=i+1;j<n;j++)
{
if(a[t]>a[j])
{
t=j;
}
}
s=a[t];
a[t]=a[i];
a[i]=s;
}
}
算法复杂度为O(N²)
希尔排序
希尔排序相当于升级版的插入排序,我们知道插入排序在处理排列比较整齐的数列时有很好的表现,希尔排序实际上就是把一个数组分成几组,对每个小组进行插入排序,再逐渐缩小分组,直到每一组只有一个元素。
具体原理请移步希尔排序,只看这篇文章的图解就行了,他使用Java实现的。
每次的step也就是每组的大小,一般默认为int(array.lenth/2),并且每次都除二。
void xierpaixu(int *a,int n)
{
for(int s=n/2;s>=1;s=s/2)
{
for(int i=s;i<n;i++)
{
int j=i;
int x=a[j];
while(j-s>=0&&x<a[j-s])
{
a[j]=a[j-s];
j=j-s;
}
a[j]=x;
}
}
}
来源:CSDN
作者:正在学Python的猛男小鞠
链接:https://blog.csdn.net/weixin_45939019/article/details/104107756