5,箱排序
//箱排序
/*
箱排序思想:
按照某种规律,把数据分成若干个箱子装起来,
箱子内部(可以用其他排序方式)
最后把箱子组合在一起;
*/
#include<stdio.h>
#include<string.h>
//数据个数
#define NUM 10
//数据范围
#define AREA 1000
//箱子个数
#define BOX_SIZE 10
void bucket_sort(int* arr, int len);
void bucket_sort(int* arr, int len)
{
int count;//放箱子次数
//1,创建箱子
int* pTemp = new int[BOX_SIZE * len];
for (count = 1; count < AREA; count *= 10)
{
//0,设计好循环
//当前关注的位 arr[i]/count%10
//2,初始化箱子
memset(pTemp, 0, sizeof(int) * (BOX_SIZE * len));
//3,把数据放到箱子里面
for (int i = 0; i < len; i++)
{
//二维数组写法//ptemp[arr[i] / count % 10][i]=arr[i];
pTemp[(arr[i] / count % 10) * len + i] = arr[i];
}
//4,把数据从箱子里拿出,覆盖原来的数组
int k = 0;
for (int i = 0; i < BOX_SIZE * len; i++)
{
if (pTemp[i])
{
arr[k] = pTemp[i];
k++;
//arr[k++]=pTemp[i];
}
}
travel(arr, len);
}
//5,释放箱子内存空间
delete[] pTemp;
}
/*
实际效果:
before: 51 65 48 355 478 666 567 3 47 9
51 3 65 355 666 567 47 48 478 9 //第一次
3 9 47 48 51 355 65 666 567 478
3 9 47 48 51 65 355 478 567 666
after: 3 9 47 48 51 65 355 478 567 666
*/
6,基数排序
/*
基数排序思想:
利用数组下标的天然有序的方式来排序;
限制1:待排数组中不能有重复数据;
限制2:要考虑负数的问题;
限制3:空间浪费地多;
*/
/*
稳定性:
1 不稳定:shell排序 快速排序 插入排序 选择排序
如果数据不同 时间复杂度也不一样
2 稳定: 箱排序 基数排序
如果数据不同 时间复杂度都一样
3 具体使用:
如果排序次数较少:使用稳定的排序
如果排序次数较多:使用不稳定的排序
*/
#include<stdio.h>
#include<string.h>
//数据个数
#define NUM 10
void radix_sort(int* arr, int len,int max);
void radix_sort(int* arr, int len, int max)
{
//1 申请临时数组内存
int* pTemp = new int[max + 1];
//2 初始化临时数组
memset(pTemp, 0, sizeof(int) * (max + 1));
//3 把待排数组放到临时数组中去
for (int i = 0; i < len; i++)
{
pTemp[arr[i]] = arr[i];
}
//4 从临时数组中把元素覆盖回待排数组
int k = 0;
for (int i = 0; i < max + 1; i++)
{
if (pTemp[i])
{
arr[k++] = pTemp[i];
}
}
//5 释放临时数组内存
delete[] pTemp;
}
/*
实际效果:
before: 51 65 48 355 478 666 567 3 47 9
after: 3 9 47 48 51 65 355 478 567 666
*/
7,快速排序
/*
快速排序思想:
给整个数组找一个中间值,
保证中间值左边的都比中间值小;
保证中间值右边的都比中间值大;
左边这一组继续分;
右边这一组继续分;
一直分到无法分(数组只有一个元素)为止
步骤:
1 设left下标0 设right下标len-1
2 假设中间值temp为arr[0]
3 循环
arr[right] 和 temp比较
比temp大 right左移
比temp小 循环结束
arr[left]=arr[right];
arr[left] 和 temp比较
比temp大 循环结束
比temp小 left右移
4 left和right相等
arr[left]=temp;
*/
#include<stdio.h>
#include<string.h>
//数据个数
#define NUM 10
void quick_sort(int* arr, int len);
//具体实现分组
void Quick_sort(int* arr, int right, int left);
void Quick_sort(int* arr, int left, int right)
{
if (left >= right)return; //一直分到无法分(数组只有一个元素)为止
//把数组分为两组
int temp = arr[left];
int L = left;
int R = right;
while (L < R)
{
while (L < R && arr[R]>temp)
{
R--;
}
arr[L] = arr[R];
while (L < R && arr[L] < temp)
{
L++;
}
arr[R] = arr[L];
}
arr[L] = temp;
//测试
printf("左边:(%d -- %d)右边:(%d -- %d)",
left, L - 1, L + 1, right);
travel(arr, 10);
/*
测试结果:
左边:(0 -- 3)右边:(5 -- 9)9 47 48 3 51 666 567 478 355 65
左边:(0 -- 0)右边:(2 -- 3)3 9 48 47 51 666 567 478 355 65
左边:(2 -- 2)右边:(4 -- 3)3 9 47 48 51 666 567 478 355 65
左边:(5 -- 8)右边:(10 -- 9)3 9 47 48 51 65 567 478 355 666
左边:(5 -- 4)右边:(6 -- 8)3 9 47 48 51 65 567 478 355 666
左边:(6 -- 7)右边:(9 -- 8)3 9 47 48 51 65 355 478 567 666
左边:(6 -- 5)右边:(7 -- 7)3 9 47 48 51 65 355 478 567 666
*/
//组内继续分组
Quick_sort(arr, left, L-1);//左边这一组
Quick_sort(arr, L + 1, right);//右边这一组
}
void quick_sort(int* arr, int len)
{
Quick_sort(arr, 0, len - 1);
travel(arr,len);
}
/*
实际效果:
before: 51 65 48 355 478 666 567 3 47 9
after: 3 9 47 48 51 65 355 478 567 666
*/
8,归并排序
/*
分治思想:分而治之
快速排序:一分为二
归并排序:两个有序数组合并为一个有序数组
*/
/*
归并排序:两个有序数组合并为一个有序数组
两个指针分别指向两个有序数组
循环遍历并且比较,符合要求的数据存放到最终的内存段中,并且指针后挪;
直到有一个数组存放完毕,循环结束;
将没有放完的数组拷贝到最终的内存段中;
*/
#include<stdio.h>
#include<string.h>
//归并排序
void merge_sort(int* arr, int len);
//递归拆分 left:左边一半第一个元素下标,right:右边一半最后一个元素的下标
void split(int* arr, int left, int right);
//合并 left:左边一半第一个元素下标,mid:左边一半最后一个元素下标,right:右边一半最后一个元素的下标
void combine(int* arr, int left, int mid, int right);
void print(int* arr, int len);
int main()
{
int arr[10] = { 15,32,89,456,133,20,46,57,77,966 };
printf("before :");
print(arr, 10);
merge_sort(arr, 10);
printf("after :");
print(arr, 10);
return 0;
}
void merge_sort(int* arr, int len)
{
split(arr, 0, len - 1);
}
void split(int* arr, int left, int right)
{
if(left < right)//保证拆分到只有一个元素就停止
{
//算中间值
//int mid = (right - left) / 2 + left;
int mid = (left+right)/2;
//拆分
split(arr, left, mid);//拆左边
split(arr, mid + 1, right);//拆右边
//合并
combine(arr, left, mid, right);
print(arr + left, right - left + 1);
}
}
void combine(int* arr, int left, int mid, int right)
{
//申请临时内存段
int len = right - left + 1;
int* pTemp = new int[len];
//循环比较并把数据有序放到pTemp
int l = left;//左边一半
int r = mid+1;//右边一半
int k = 0;//pTemp的下标
while (l <= mid && r <= right)
{
if (arr[l] < arr[r])
{
pTemp[k++] = arr[l++];
}
else
{
pTemp[k++] = arr[r++];
}
}
//把剩下的也放到pTemp
#if 1
while(l<=mid)pTemp[k++] = arr[l++];
while(r<=right)pTemp[k++] = arr[r++];
#else
if (l <= mid)//左边没放完
{
memcpy(pTemp + k, arr + l, sizeof(int) * (mid - l + 1));
}
else//右边还没有放完
{
memcpy(pTemp + k, arr + right, sizeof(int) * (right - r + 1));
}
k += (right - r + 1);
#endif
//pTemp覆盖回arr中
memcpy(arr + left, pTemp, sizeof(int) * len);
//释放pTemp
delete[] pTemp;
}
void print(int* arr, int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}