排序算法(Assending)
总结了B站左神课上的一些排序算法,加上我自己整理了一些,基本所有的排序算法都在里面了
以下所有排序算法都经过上万次测试
一些算法和对数器中需要用到的公用方法
void Swap(int* arr, int a, int b) {
int t = arr[a];
arr[a] = arr[b];
arr[b] = t;
}
int Abs(int n)
{
return n < 0 ? -n : n;
}
int Min(int a, int b)
{
return a < b ? a : b;
}
int Max(int a, int b) {
return a > b ? a : b;
}
int GetDigit(int num, int digit) {
return num / (int)pow(10, digit - 1) % 10;
}
void PrintArray(int* arr, int len) {
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
/// <summary>
/// 生成len个区间[L,R]的随机数并放入长度为len的数组中,注意使用前要加上srand((unsigned int)time(NULL));
/// </summary>
void GenerateRandomArray(int* arr, int len, int min, int max) {
for (int i = 0; i < len; i++)
arr[i] = rand() % (max - min + 1) + min;
}
主函数中对于对数器的实现,用于验证算法的正确性
#include <algorithm>//包含stdio.h即scanf和printf以及is_sorted等排序函数
int main()
{
srand((unsigned int)time(NULL));//设置随机数种子(时间种子)
DWORD t1 = timeGetTime();
const int len = 5;
int arr[len];
int sortTimes = 10000;
for (int i = 1; i <= sortTimes; i++)
{
GenerateRandomArray(arr, len, 2, 10);//生成随机数组
if (arr == nullptr || len < 2);//本身就有序,无需排序
else {
// PrintArray(arr, len);
BucketSort(arr, len);
}
if (is_sorted(arr, arr + len, less<int>()));
else
{
PrintArray(arr, len);
printf("Error!!!\n");
system("pause");
}
}
printf("平均每次运行时间:%f", (timeGetTime() - t1) * 1.0 / sortTimes);
return 0;
}
排序算法
// 注意!!!!!!如果是new了新的对象,一定要delete掉!!!!!!
///————————基于比较的排序————————
#pragma region 选择排序
void selectSort(int* arr, int len)
{
for (int i = 0; i <= len - 2; i++)
{
int k = i;
for (int j = i; j <= len - 1; j++)
{
if (arr[k] > arr[j])k = j;
}
if (k != i)Swap(arr, k, i);
}
}
#pragma endregion
#pragma region 冒泡排序
void bubbleSort(int* arr, int len)
{
for (int i = 0; i <= len - 2; i++)
{
for (int j = 0; j <= len - 2 - i; j++)//最后的i个数已经有序
{
if (arr[j] > arr[j + 1])
Swap(arr, j, j + 1);
}
}
}
#pragma endregion
#pragma region 插入排序
void insertSort(int* arr, int len)
{
for (int i = 1; i <= len - 1; i++)
{
int j,temp = arr[i];
for (j = i; j > 0 && temp < arr[j - 1]; j--)
{
arr[j] = arr[j - 1];
}
arr[j] = temp;
}
}
#pragma endregion
#pragma region 快速排序--(衍生自)-->冒泡排序
int* partition(int* arr, int i, int num)
{//相当于荷兰国旗问题 i为指针,初始指向第一个数;arr[num]为划分值
int L = i - 1;//左边界
int R = num;//右边界
while (i < R)
{
if (arr[num] > arr[i])
Swap(arr, ++L, i++);
else if (arr[num] < arr[i])
Swap(arr, --R, i);
else
i++;
}
Swap(arr, R++, num);
int p[2] = { L + 1, R - 1 };
return p;
}
void quickSort(int* arr, int L, int R)
{
Swap(arr, rand() % (R - L + 1) + L, R);
int* p = partition(arr, L, R);
//数组的[p[0], p[1]]区间为等于区间
if (L < p[0] - 1)
quickSort(arr, L, p[0] - 1);
if (p[1] + 1 < R)
quickSort(arr, p[1] + 1, R);
}
#pragma endregion
#pragma region 归并排序--(衍生自)-->分治
void mergeCompare(int* arr, int L, int Mid, int R)
{
int i = L;
int j = Mid + 1;
// 创建一个辅助数组
// {}表示将新分配的int数组中的所有元素初始化为零
int* ans = new int[R - L + 1]{};
int k = 0;
while (i <= Mid && j <= R)
ans[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
while (i <= Mid)
ans[k++] = arr[i++];
while (j <= R)
ans[k++] = arr[j++];
for (k = 0; k < R - L + 1; k++)
arr[L + k] = ans[k];
delete[] ans;//释放辅助数组的空间
}
void mergeSort(int* arr, int L, int R)
{
if (L == R)
return;
int Mid = L + ((R - L) >> 1);
mergeSort(arr, L, Mid);
mergeSort(arr, Mid + 1, R);
mergeCompare(arr, L, Mid, R);
}
#pragma endregion
#pragma region 堆排序
void heapify(int* arr, int i, int heapSize)
{//i为指针 小的数从上往下沉降,最终根节点的数最大
int left = (i << 1) + 1;
while (left < heapSize)//如果有孩子
{
int largest = arr[left] < arr[left + 1] && left + 1 < heapSize ? left + 1 : left;
largest = arr[largest] > arr[i] ? largest : i;
if (largest == i)break;
Swap(arr, largest, i);
i = largest;
left = (i << 1) + 1;
}
}
void heapSort(int* arr, int len)
{//大根堆 升序
for (int i = len - 1; i >= 0; i--)//O(N)
heapify(arr, i, len);//O(1)
int heapSize = len;
Swap(arr, 0, heapSize - 1);//下标位置从0开始,最后要减一
heapSize--;
while (heapSize > 0)//O(N)
{
heapify(arr, 0, heapSize);//O(logN)
Swap(arr, 0, heapSize - 1);
heapSize--;
}
}
#pragma endregion
#pragma region 希尔排序--(衍生自)-->插入排序
void shellSort(int* arr, int len)
{
const int divide = 3;
int gap = len / divide + 1;//为保证gap至少为1
while (gap)
{
for (int i = gap; i <= len - 1; i++)
{
int j, temp = arr[i];
for (j = i; j > 0 && temp < arr[j - gap]; j -= gap)
arr[j] = arr[j - gap];
arr[j] = temp;
}
gap /= divide;
}
}
#pragma endregion
// 锦标赛排序—(衍生自)— > 选择排序,堆排序
// tim排序—(衍生自)—>插入排序,归并排序
///————————不基于比较的排序————————
#pragma region 桶排序
void BucketSort(int* arr, int len) {
// 获取最大值和最小值
int maxVal = arr[0];
int minVal = arr[0];
for (int i = 0; i < len; i++) {
if (maxVal < arr[i])
maxVal = arr[i];
if (minVal > arr[i])
minVal = arr[i];
}
// 计算区间(桶)的数量
int bucketCount = (maxVal - minVal) / len + 1;
// 用于存放每个区间中元素的个数
// {}用于初始化数组,使得每个值都为0
int* intervals = new int[bucketCount] {};
// 桶数组,用于存放每个桶中的数据,int[i][j]表示第i个桶中存放的第j个数据
int** buckets = new int* [bucketCount]; // 创建指向一维数组的指针
for (int i = 0; i < bucketCount; i++) buckets[i] = new int[len]; // 为每个一维数组分配内存
int bucketSize = (maxVal - minVal) / bucketCount + 1;
for (int i = 0; i < len; i++) {
// 数组元素所在的桶
int index = (arr[i] - minVal) / bucketSize;
buckets[index][intervals[index]] = arr[i];
intervals[index]++;
}
int k = 0;
for (int i = 0; i < bucketCount; i++) {
int j;
if (intervals[i] > 0) {
// 将桶中的元素放入源数组中
for (j = 0; j < intervals[i]; j++) {
arr[k++] = buckets[i][j];
}
// 快速排序
quickSort(arr, k - j, k - 1);
}
}
delete[] intervals;
for (int i = 0; i < bucketCount; i++) delete[] buckets[i]; // 释放每个一维数组的内存
delete[] buckets;
}
#pragma endregion
#pragma region 计数排序--(衍生自)-->桶排序
void countingSort(int* arr, int len)
{
//年龄[0,99]
int barrel[101]{};
int k = -1;
for (int i = 0; i < len; i++)
{
barrel[arr[i]]++;
}
for (int i = 0; i < 100; i++)
{
while (barrel[i] > 0) {
arr[++k] = i;
barrel[i]--;
}
}
}
#pragma endregion
#pragma region 基数排序--(衍生自)-->桶排序
int maxBits(int* arr, int len)
{
int max = arr[0];
for (int i = 1; i <= len - 1; i++)
max = Max(max, arr[i]);
int res = 0;
while (max != 0)
{
max /= 10;
res++;
}
return res;
}
void radix(int* arr, int L, int R, int digit)
{
const int radix = 10;
int i = 0, j = 0;
int* bucket = new int[R - L + 1];
for (int d = 1; d <= digit; d++)
{
int count[radix]{};
for (int i = L; i <= R; i++)//统计
{
int j = GetDigit(arr[i], d);
count[j]++;
}
for (int i = 1; i < radix; i++)//累加
count[i] = count[i - 1] + count[i];
for (int i = R; i >= L; i--)//将原数组的数按次序放入桶数组中
{
int j = GetDigit(arr[i], d);
bucket[--count[j]] = arr[i];
}
for (int i = 0, j = L; j <= R; i++, j++)//把排好一轮的数放回原数组中
arr[j] = bucket[i];
}
delete[] bucket;
}
void radixSort(int* arr, int len)
{
radix(arr, 0, len - 1, maxBits(arr, len));
}
#pragma endregion