归并排序:
基本思想:先递归再回归,在回归的时候进行归并排序
归并排序:
适用于两个有序数组,合并成一个数组的时候,也就是先要递归,递归到最后就相当于一个元素,一个元素就是有序的。
之后回归时再进行两两元素的排序。
代码如下:
void PartSort1(int *a,int n)
{
int* tmp = (int*)malloc(n * sizeof(int));
if (tmp == NULL)
{
perror("malloc:error");
return;
}
int begin = 0;
int end = n - 1;
MergeSort(a,tmp,begin,end);
}
void MergeSort(int* a, int *tmp,int begin,int end)
{
if (begin >= end)
{
return;
}
int mid = (begin + end) / 2;
MergeSort(a,tmp,begin,mid);
MergeSort(a, tmp, mid+1,end);
//递归
int begin1 = begin;
int end1 = mid;
int begin2 = mid + 1;
int end2 = end;
int i = begin1;
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] < a[begin2])
{
tmp[i++] = a[begin1++];
}
else
{
tmp[i++] = a[begin2++];
}
}
while (begin1 <= end1)
{
tmp[i++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[i++] = a[begin2++];
}
memcpy(a+begin,tmp+begin,(end-begin+1)*sizeof(int));//这里一点更要加i,不是加begin也不是加begin1
}
非递归归并排序:
void MergeSort1(int* a, int n)
{
int* tmp = (int*)malloc(n * sizeof(int));
if (tmp == NULL)
{
perror("malloc:error");
return;
}
int gap = 1;//表示gap个元素为一组
while (gap < n)
{
for (int i = 0; i < n ; i+=2*gap)
{
int begin1 = i;
int end1 = i + gap - 1;
int begin2 = i +gap;
int end2 = i + 2 * gap-1;
int j = begin1;
//边界处理
if (end1 >= n || begin2 >= n)
{
break;
}
if (end2 >= n)
{
end2 = n - 1;
}
printf("[%d %d] [%d %d]", begin1, end1, begin2, end2);
while (begin1 <= end1 && begin2 <= end2)
{
if (a[begin1] < a[begin2])
{
tmp[j++] = a[begin1++];
}
else
{
tmp[j++] = a[begin2++];
}
}
while (begin1 <= end1)
{
tmp[j++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[j++] = a[begin2++];
}
memcpy(a + i, tmp + i, (end2-i+1) * sizeof(int));
}
printf("\n");
gap *= 2;
}
}
计数排序:
如果有排序可以统计小范围数据,并且效率较高,比其他排序效率都要高一点,那肯定是基数排序。
原理:
要对一组数进行排序,可以统计每个数出现的次数。
此时需要开辟一个新数组(新数组的长度等于原数组最大值 - 最小值),从头开始统计原数组的每个数出现的次数,每出现一次,在新数组的对应下标位置加1。直到原数组统计结束。
再将新数组里的数从头一次放回原数组中。
例如:
代码如下:
void Countingsort(int* a, int n)
{
//找最大值
int max = a[0];
for (int i = 0; i < n; i++)
{
if (a[i] > max)
{
max = a[i];
}
}
int size = max+ 1;
int* tmp = (int*)calloc(size ,sizeof(int));
if (tmp == NULL)
{
perror("calloc:error");
return;
}
for (int i = 0; i < n; i++)
{
tmp[a[i]]++;
}
int i = 0;
for (int j = 0; j < size; j++)
{
while (tmp[j] != 0)
{
a[i++] = j;
tmp[j]--;
}
}
free(tmp);
}
但是这样做的话,效率会有点低,导致在遇到大数的时候,得开辟从0~max的大小的空间。
但是如果我只有1000~1999的数据,会造成前面空间的浪费。
因此进一步改进:(优化!!)
代码如下:
void Countingsort(int* a, int n)
{
//找最大值和最小值
int max = a[0];
int min = a[0];
for (int i = 0; i < n; i++)
{
if (a[i] > max)
{
max = a[i];
}
if (a[i] < min)
{
min = a[i];
}
}
int size = max - min + 1;
int* tmp = (int*)calloc(size, sizeof(int));
if (tmp == NULL)
{
perror("calloc:error");
return;
}
//往tmp里面放值
for (int i = 0; i < n; i++)
{
tmp[a[i] - min]++;
}
//tmp里面取值
int i = 0;
for (int j = 0; j < size; j++)
{
while (tmp[j] != 0)
{
a[i++] = j+min;
tmp[j]--;
}
}
free(tmp);
}