排序算法(3)
归并排序
算法描述:将待排序的元素序列分为两个长度相等的子序列,对每个子序列进行排序,然后将他们合并成一个序列,合并两个子序列的过程称为二路归并.
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<assert.h>
//归并
void MergeData(int *arr,int left,int mid,int right,int *temp){
int temp_index = left;
int left_L = left;
int left_R = mid;
int right_L = mid;
int right_R = right;
while (left_L<left_R && right_L<right_R)
{
if (arr[left_L]<arr[right_L])
{
temp[temp_index++] = arr[left_L++];
}
else
{
temp[temp_index++] = arr[right_L++];
}
}
while(left_L<left_R)
{
temp[temp_index++] = arr[left_L++];
}
while (right_L<right_R)
{
temp[temp_index++] = arr[right_L++];
}
}
//分组
//void *memcpy(void*dest, const void *src, size_t n);
//由src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内。
void _MergeSort(int *arr, int left, int right, int *temp){
if ((right-left)>1)
{
int mid = left + ((right-left)>>1);
_MergeSort(arr,left,mid,temp);
_MergeSort(arr, mid, right, temp);
MergeData(arr,left,mid,right,temp);
memcpy(arr+left,temp+left,sizeof(int)*(right-left));
}
}
//递归
void MergeSort(int *arr,int size){
int *temp = (int *)malloc(size*sizeof(arr[0]));
if (temp==NULL)
{
assert(0);
return;
}
_MergeSort(arr,0,size,temp);
free(temp);
}
//非递归
void MergeSort_Nor(int *arr, int size){
int *temp = (int *)malloc(size*sizeof(arr[0]));
if (temp == NULL)
{
assert(0);
return;
}
int i = 0;
int gap = 1;
while (gap<size)
{
for (i = 0; i < size;i+=2*gap){
int left = i;
int mid = left + gap;
int right = mid + gap;
if (mid>size)
{
mid = size;
}
if (right>size)
{
right = size;
}
MergeData(arr, left, mid, right, temp);
}
memcpy(arr,temp,size*sizeof(arr[0]));
gap=gap*2;
}
free(temp);
}
int main(){
int arr[10] = { 2, 0, 4, 9, 3, 6, 8, 7, 1, 5 };
int size = sizeof(arr) / sizeof(arr[0]);
MergeSort(arr,size);
//MergeSort_Nor(arr, size);
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
system("pause");
return 0;
}
计数排序
算法描述:找到待排序列中最大最小的元素,然后以此确定临时空间的大小,在临时空间中,以待排序列组中元素的大小为下标,该元素出现的次数为该下标对应的元素,根据临时空间的统计结果,重新对元素进行回收.
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<malloc.h>
int GetMaxValue(int *arr,int size){
int i = 0;
int max = arr[0];
for ( i = 1; i < size; i++)
{
if (arr[i]>max)
max = arr[i];
}
return max;
}
int GetMinValue(int *arr, int size){
int i = 0;
int min = arr[0];
for (i = 1; i < size; i++)
{
if (arr[i]<min)
min = arr[i];
}
return min;
}
void _Count_Sort(int *arr, int *temp,int size,int ret,int min){
int i = 0;
int index = 0;
//统计个数
for ( i = 0; i < size; i++)
{
temp[arr[i]-min]++;
}
//回收,把temp里的数据回收到原空间里
for ( i = 0; i <ret ; i++)
{
while (temp[i]--)
{
arr[index++] = i+min;
}
}
free(temp);
}
void Count_Sort(int *arr,int size){
int max = GetMaxValue(arr,size);
int min = GetMinValue(arr, size);
int ret = max - min + 1;
int *temp = (int *)malloc(ret*sizeof(arr[0]));
if (temp==NULL)
{
assert(0);
return;
}
//memset作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法
memset(temp,0,ret*sizeof(int));
_Count_Sort(arr,temp,size,ret,min);
}
int main(){
int i = 0;
int arr[10] = {3,4,3,2,1,2,6,5,4,7};
int size = sizeof(arr) / sizeof(arr[0]);
Count_Sort(arr,size);
for ( i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
system("pause");
return 0;
}
基数排序
算法描述:把待排序中的元素按照低位先排序,然后收集,再按照高位排序,再收集,直至最高位.①,获取序列中的最大数,然后取得其位数,然后利用计数排序的特点,定义10个元素的数组,分别统计以待排序列元素的每一位为数组的下标的元素的个数,然后再定义一个数组存每个的起始地址.开一个辅助空间,放置元素.再回收这些元素.
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>
#include<string.h>
//统计最大元素的位数
int GetMaxValue_BitCount(int *arr,int size){
int i = 0;
int count = 1;
int ret = 10;
for ( i = 0; i < size; i++)
{
while (arr[i] >= ret)
{
count++;
ret *= 10;
}
}
return count;
}
void _RadixSort(int *arr,int size,int *temp){
int Max_BitCount = GetMaxValue_BitCount(arr, size);
//存每个桶中元素的个数.
int count[10] = { 0 };
//存每个桶的起始地址
int start_Addr[10] = { 0 };
int i = 0;
int ret = 1;
int index = 0;
while (Max_BitCount)
{
//统计个数
for ( i = 0; i < size; i++)
{
count[arr[i] / ret % 10]++;
}
//计算地址
for ( i = 1; i < 10; i++)
{
start_Addr[i] = start_Addr[i - 1] + count[i - 1];
}
//放置元素到临时空间中
for (i = 0; i <size; i++){
int Addr = arr[i]/ret% 10;
temp[start_Addr[Addr]++] = arr[i];
}
//回收元素
//memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
//void *memcpy(void *dest, const void *src, size_t n);
memcpy(arr,temp,size*sizeof(arr[0]));
ret *= 10;
Max_BitCount--;
}
}
void RadixSort(int *arr,int size){
int *temp = (int *)malloc(size*sizeof(arr[0]));
if (temp==NULL)
{
assert(0);
return;
}
_RadixSort(arr,size,temp);
free(temp);
}
int main(){
int arr[11] = {198,254,378,852,761,554,581,552,605,479,853};
int size = sizeof(arr) / sizeof(arr[0]);
RadixSort(arr,size);
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
system("pause");
return 0;
}