对常见排序做一些总结,做到烂熟于心
排序算法在数据结构中很常见,插入、交换、归并、堆排序,很多,首先,给出算法的复杂度,备查找。如下图,
插入排序
1.直接插入
直接插入的思想很简单,整个序列分为有序区和无序区,将第一个元素作为有序区的元素,依次将无序区的元素插入到有序区的合适位置,直到整个序列有序,通俗的说:就像我们小时候老师按大小个排队,从第二个出发,将其与之前的作对比,若满足比之前的大,比其之后的小,则插入其中,直至大小排好序。以下为c++
代码实现:
#include<iostream>
using namespace std;
void Swap(int *a, int *b)//交换
{
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
void insertSort(int *a,int len)
{
for (int i = 0; i < len; i++)
{
for (int j = i; j > 0 ; j--)
{
if (a[j] < a[j - 1])
{
Swap(&a[j], &a[j - 1]);
}
}
}
}
int main()
{
int a[] = { 1, 7, 3, 2, 8 ,2,4,5,6,43,2,1,8};
insertSort(a, 13);
for (size_t i = 0; i < 13; i++)
{
cout << a[i] << endl;
}
return 0;
}
对于其时间复杂度如果是原始序列就是正序序列,执行n次,复杂度为`o(n-1)`,最坏情况是倒序序列,执行(1+2+...+n)=(n-1)*n/2次数,复杂度是`o(n*n)`。
交换排序
冒泡排序
冒泡排序的思想:将整个序列分为无序序列和有序序列,将相邻的元素进行比较,是大的数放在小的数后面,简单的实例如图:
c++实现如下:
void BubbleSort(int *a, int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i -1; j++)
{
if (a[j + 1] < a[j])
Swap(&a[j + 1], &a[j]);
}
}
}
冒泡复杂度,和插入的复杂度类似,最坏情况是o(n*n)
,最好情况是o(n)
,所以在数较少是效果较好,是稳定的排序。
冒泡还有个更加优化的排序,我们在排序中可以看到,当序列已经有序,或者已经经过交换,那么这个就不必要去执行,浪费时间,那么可以把交换的位置记下,因为这个是先找到最重的(从小到大排序),那么可以一次循环 ,减少循环次数,节省了时间。
快速排序
快速排序的思想是,找到一个轴,遍历数组里的值,小于轴值的放在左边,大于等于轴值的放在右边,具体实现可以利用递归实现,c++程序如下:
int onceSort(int *a, int first, int end)
{
int i = first;
int j = end;
while (i<j)
{
while (i<j &&a[i]<=a[j]) j--;
//如果跳出循环则说明,i>j,或者a[i]>a[j],加入i<j的情况下,那么必有a[i]>a[j],使之可以跳出循环,
if (i < j)
{
Swap(&a[i], &a[j]);//按照快速排序的思想可以得出,将小的放在轴值左边,大的放在轴值右边,现在a[i]>a[j,]那么就需要交换
}
//同样的对于i,也做相同的操作
while (i < j&&a[i] <= a[j]) i++;
if (i < j)
{
Swap(&a[i], &a[j]);
}
}
return i;
}
void quickSort(int *a, int first, int end)
{
int provcLoc;
if (first < end)
{
provcLoc = onceSort(a, first, end);
quickSort(a, first, provcLoc-1);
quickSort(a, provcLoc + 1, end);
}
}
快速排序时间复杂度,最差是o(n*n)
,最好是o(n*log2n)。