今早犯了一次瓜,让我纠结了一个小时这里为这次的傻逼总结一次:
不是昨天写了堆排序吗,早上又重新写了一便,可是发现代码没问题呀:但是为啥呢?
现在就来总结一下
void sort(int *a, int index, int size)
{
int left = index * 2 + 1;
while (left < size)
{
int larger = (left + 1 < size && a[left + 1]) > a[left] ? left + 1 : left;
larger = a[larger] > a[index] ? larger : index;
if (larger == index)
{
break;
}
swap(&a[larger], &a[index]);
index = larger;
left = (index * 2) + 1;
}
}
其中有一段代码是这样int larger = left + 1 < size && a[left + 1] > a[left] ? left + 1 : left;
我写成了这样int larger = left + 1 < size && a[left] > a[left+1] ? left : left+1;
我乍一看没啥毛病呀,到底是为啥呢?仔细分析之后我写了下面的代码
void sort(int *a, int index, int size)
{
int left = index * 2 + 1;
while (left < size) //先判断是孩子是否存在
{
int larger = left + 1;
if (larger < size) //再判判断右孩子是否存在,存在的话寻找,左孩子,右孩子,和要调整位置的大小
{
larger = a[left] > a[left + 1] ? left : larger;
larger = a[larger] > a[index] ? larger : index;
if (larger == index)
{
break;
}
swap(&a[larger], &a[index]);
index = larger;
left = (index * 2) + 1;
}
else //如果没有右孩子则会走到这一步,这一步判断的就是左孩子和需要调整位置的大小
{
larger = a[index] > a[left] ? index : left;
if (larger == index)
{
break;
}
swap(&a[larger], &a[index]);
index = larger;
left = (index * 2) + 1;
}
}
}
写完上面代码不就是判断了一个右孩子是否存在吗?我再回头看了看代码
int larger = left + 1 < size && a[left + 1] > a[left] ? left + 1 : left;
·············这,我居然犯了这个错误,我把 left + 1 < size 和a[left + 1] > a[left] ? left + 1 : left;
看成了两个部分,怪不得错了,这个其实是int larger = ( left + 1 < size && a[left + 1] > a[left] ) ? left + 1 : left;
看来平时写的时候还是要带括号,不然自己眼睛都看花了,罪过,罪过。。。。。。
new出来的数组,如果不初始化就是随机值。
merge sort(归并排序)
quicksort(快排)
coding:扣丁,写代码,编码。
系统中的排序,比如array.sort()
这个就是一个综合排序,意思就是你要排的一个无序数组的长度小于60,则可能直接进行插入排序,要是大于60可能进行快排或者归
并排序,在进行插入或者快排的时候不是存在一个要进行划分吗,对数组的元素进行分割,分割的时候如果发现元素小于60,那么就
会直接进行插入排序,就不再向下分割了(我们再进行经典快拍的时候往往要分隔到独立的元素再开始返回),这就叫综合排序。
原因就是因为插入排序,虽然它的时间复杂度是o(N^2),但是在每次排序的时候插入排序内部常数项比较小(也就是每一次循环内部
的操作比较少),所以在数据量较小的时候,会选择插入排序。那么在大于60的时候什么时候选择归并排序,什么时候选择快排呢?
在数据类型是基础类型的时候,int,char double的时候 就会选择快排,而在处理自定义类型的是就会选择归并排序。但是这个又是为
什么呢?那就是稳定性,底层是按稳定性来规定的。但是为什么基础数据类型的排序要用快排,这是因为基础类型排序的时候不关心稳
定性,(为什么不关心呢?因为大家都是一相同的元素,排序的是时候根本不需要区分)所以在自定义类型的时候用归并排序。
桶排序:(一种基于数据状况的排序)
在工程上用的并不多,因为每次都要分析数据状况,不方便。
不基于比较的排序快但是不方便
常见的有两种计数排序
桶排序之计数排序
#include<stdio.h>
void sort(int *a, int length)
{
int max = a[0]; //一个数组先拿出这个数组中的最大值
for (int i = 0; i < length; ++i)
{
if (a[i]>max)
{
max = a[i];
}
} //等到这一步结束已经拿到了数组的最大值
int *p = new int[max + 1]; //拿到最大值的话就申请0-最大值之间个空间大小的数组
printf("%d", p[0]);
for (int i = 0; i < max + 1; ++i) //拿到数组之后不要忘记初始化,先把数据初始化成0
{
p[i] = 0;
}
for (int i = 0; i < length; ++i) //然后再从需要排序的数组里面挨个拿出数字在进行统计的数组中自增
{
p[a[i]]++;
}
int j = 0;
for (int i = 0; i < max + 1; ++i) //这一步就是再把数据填充到原来的数组里面
{
while ((p[i]--)>0)
{
a[j++] = i;
}
}
}
int main()
{
int a[] = { 9, 7, 8, 5, 4, 6, 2, 1, 3, 0, 5, 8, 9, 2, 5, 2, 4, 6, 2, 4, 8, 2, 1, 5, 3, 2, 2, 1, 4, 7, 8, 9, 6, 3, 0, 1, 2, 5, 4, 8, 9, 6, 4 };
int c = sizeof(a) / sizeof(int);
sort(a, c);
for (int i = 0; i < c; ++i)
{
printf("%d", a[i]);
}
return 0;
}