归并排序:
基本思想:先递归再回归,在回归的时候进行归并排序

归并排序:
适用于两个有序数组,合并成一个数组的时候,也就是先要递归,递归到最后就相当于一个元素,一个元素就是有序的。
之后回归时再进行两两元素的排序。
代码如下:
  
 
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);
}


















