几种主流的排序算法(C++)

排序算法(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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值