归并排序
递归代码实现归并:
void _MergeDate(int* array,int left,int mid,int right,int* temp)
{
int index1 = left;
int index2 = mid;
int index = left;
while(index1<mid && index2<right)
{
if(array[index1]<=array[index2])
temp[index++] = array[index1++];
else
temp[index++] = array[index2++];
}
while(index1<mid)
temp[index++] = array[index1++];
while(index2<right)
temp[index++] = array[index2++];
}
void _MergeSort(int* array,int left,int right,int* temp)
{
if(right-left>1)
{
//求中间位置
int mid = left+((left-right)>>1);
//归并左半区间[left,mid)
_MergeSort(array,left,mid,temp);
//归并有右区间[mid,right)
_MergeSort(array,mid,right,temp);
//归并左[left,mid)右[mid,right)区间-->temp(到temp)
_MergeDate(array,left,mid,right,temp);
memcpy(array+left,temp+left,sizeof(array[left])*(right-left));
}
}
void MergeSort(int* array,int size)
{
int* temp = (int*)malloc(sizeof(array[0])*size);
if(NULL == temp)
{
assert(0);
return ;
}
_MergeSort(array,0,size,temp);
free(temp);
}
稳定性:稳定
时间复杂度:O(NlogN)
空间复杂度:O(N);
循环代码实现归并
void MergeDate(int* array,int left,int mid,int right,int* temp)
{
int index1 = left;
int index2 = mid;
int index = left;
while(index1<mid && index2<right)
{
if(array[index1]<=array[index2])
temp[index++] = array[index1++];
else
temp[index++] = array[index2++];
}
while(index1<mid)
temp[index++] = array[index1++];
while(index2<right)
temp[index++] = array[index2++];
}
void MergeSort(int* array,int size)
{
int* temp = (int*)malloc(sizeof(array[0])*size);
if(NULL == temp)
{
assert(0);
return ;
}
int gap = 1;//用gap 标记每个分组的元素数
while(gap<size)//最少可以分为两个分组
{
for(int i = 0;i<size;i+=2*gap)
{
int left = i;
int mid = i+gap;
int right = i+2*gap;
if(mid>size)
mid = size;
if(right>size)
right = size;
//[left,mid)和[mid,right)两个区间的元素归并
MergeDate(array,left,mid,right,temp);
//法一:没归并一次拷贝一次
//memcpy(array+left,temp+left,sizeof(array[left])*(right-left));
}
//法二:没归并一趟拷贝一次
memcpy(array,temp,sizeof(array[0])*size);
gap*=2;
}
free(temp);
}
排序总结:
插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序—>内部排序:在排序时需要一次性将所有数据加载到内存中;
归并排序—>外部排序:在排序时不需要一次将所有数据加载到内存中;
比较排序
插入,希尔,选择,堆,冒泡,快速都是比较排序
非比较排序
假设:数据密集的集中在0-9的范围之中;
思考:可以申请一个有10个数的数组,将数组元素置为0;用数组元素记录0-9出现的次数,用数组下标记录数据;
//空间复杂度:O(M),M为maxVaule-minVaule+1
//时间复杂度为O(N);
//稳定性:稳定;
//使用场景:数据集中在某个位置
void CountSort(int* array,int size)
{
//求最大值,最小值
int maxVaule = array[0];
int minVaule = array[0];
for(int i = 0;i<size;i++)
{
if(array[i]>maxVaule)
maxVaule = array[i];
if(array[i]<minVaule)
minVaule = array[i];
}
//申请空间
int range = maxVaule-minVaule+1;
int* ArrayCount = (int*)malloc(sizeof(sizeof(int)*range);
memset(ArrayCount,0,sizeof(int)*range);
//统计元素出现次数
for(int i = 0;i<size;i++)
ArrayCount[array[i]-minVaule]++;
//回收
int index = 0;
for(int i = 0;i<range;i++)
{
while(ArrayCount[i]--)
array[index++] = i+minVaule;
}
}