C++ 几个常用排序的代码

15 篇文章 0 订阅
5 篇文章 0 订阅

排序算法时间复杂度(平均)时间复杂度(最坏)时间复杂度(最好)空间复杂度稳定性
冒泡排序 O ( n 2 ) O(n^{2}) O(n2) O ( n 2 ) O(n^{2}) O(n2) O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)稳定
选择排序 O ( n 2 ) O(n^{2}) O(n2) O ( n 2 ) O(n^{2}) O(n2) O ( n 2 ) O(n^{2}) O(n2) O ( 1 ) O(1) O(1)不稳定
插入排序 O ( n 2 ) O(n^{2}) O(n2) O ( n 2 ) O(n^{2}) O(n2) O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)稳定
希尔排序 O ( n 1.3 ) O(n^{1.3}) O(n1.3) O ( n 2 ) O(n^{2}) O(n2) O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)不稳定
归并排序 O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) O ( n ) O(n) O(n)稳定
快速排序 O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) O ( n 2 ) O(n^{2}) O(n2) O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n)不稳定
堆排序 O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n) O ( 1 ) O(1) O(1)不稳定
计数排序 O ( n + k ) O(n+k) O(n+k) O ( n + k ) O(n+k) O(n+k) O ( n + k ) O(n+k) O(n+k) O ( n + k ) O(n+k) O(n+k)稳定
基数排序 O ( n ∗ k ) O(n*k) O(nk) O ( n ∗ k ) O(n*k) O(nk) O ( n ∗ k ) O(n*k) O(nk) O ( n + k ) O(n+k) O(n+k)稳定
桶排序 O ( n + k ) O(n+k) O(n+k) O ( n 2 ) O(n^{2}) O(n2) O ( n ) O(n) O(n) O ( n + k ) O(n+k) O(n+k)稳定

冒泡排序

void BubbleSort(int* arr, int arrayLength)
{
	cout << "Bubble Sort:" << endl;
	for (int i = 1; i < arrayLength; i++) {
		for (int j = 0; j < arrayLength - i; j++) {
			if (arr[j] > arr[j + 1]) {
				swap(arr[j], arr[j + 1]);
			}
		}
	}
	Display(arr, arrayLength);
}

选择排序

/*
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,
然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
以此类推,直到所有元素均排序完毕。
*/
void SelectSort(int* arr, int arrayLength)
{
	cout << "Select Sort:" << endl;
	for (int i = 0; i < arrayLength - 1; ++i) {
		int minIndex = i;
		for (int j = i + 1; j < arrayLength; ++j) {
			if (arr[minIndex] > arr[j]) {
				minIndex = j;
			}
		}
		if (minIndex != i) {
			swap(arr[i], arr[minIndex]);
		}
	}
	Display(arr, arrayLength);
}

插入排序

/*
构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入
*/
void InsertSort(int* arr, int arrayLength)
{
	cout << "Insert Sort:" << endl;
	for (int i = 1; i < arrayLength; ++i) {
		for (int j = i; j > 0; --j) {
			if (arr[j - 1] > arr[j]) {
				swap(arr[j - 1], arr[j]);
			}
			else {
				break;
			}
		}
	}
	Display(arr, arrayLength);
}

希尔排序

/*
与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序
*/
void ShellSort(int* arr, int arrayLength, int step = 1)
{
	cout << "Shell Sort:" << endl;
	while (step >= 1) {
		for (int i = step; i < arrayLength; i++) {
			for (int j = i; j >= step; j -= step) {
				if (arr[j - step] > arr[j]) {
					swap(arr[j - step], arr[j]);
				}
				else {
					break;
				}
			}
		}
		step /= 2;
	}
	Display(arr, arrayLength);
}

归并排序

/*
将已有序的子序列合并,得到完全有序的序列;
即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
*/
void _MergeSort(int* arr, int first, int last, int* temp)
{
	int mid = (first + last) / 2;
	auto mergeArray = [=]()->void {
		int k = 0;
		int i = first, m = mid;
		int j = mid + 1, n = last;
		while (i <= m && j <= n) {
			temp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
		}
		while (i <= m) {
			temp[k++] = arr[i++];
		}
		while (j <= n) {
			temp[k++] = arr[j++];
		}
		for (i = 0; i < k; ++i) {
			arr[first + i] = temp[i];
		}
	};
	if (first < last) {
		_MergeSort(arr, first, mid, temp);
		_MergeSort(arr, mid + 1, last, temp);
		mergeArray();
	}
}
void MergeSort(int* arr, int arrayLength)
{
	cout << "Merge Sort:" << endl;
	int* temp = new int[arrayLength];
	_MergeSort(arr, 0, arrayLength - 1, temp);
	delete temp;
	Display(arr, arrayLength);
}

快速排序

/*
通过一趟排序将待排记录分隔成独立的两部分,
其中一部分记录的关键字均比另一部分的关键字小,
则可分别对这两部分记录继续进行排序,以达到整个序列有序。
*/
void _QuickSort(int* arr, int left, int right)
{
	auto partition = [=]()->int {
		int key = arr[right];
		int i = left;
		for (int m = left; m < right; ++m) {
			if (arr[m] <= key) {
				swap(arr[i++], arr[m]);
			}
		}
		swap(arr[i], arr[right]);
		return i;
	};
	if (left < right) {
		int p = partition();
		_QuickSort(arr, left, p - 1);
		_QuickSort(arr, p + 1, right);
	}
}
void QuickSort(int* arr, int arrayLength)
{
	cout << "Quick Sort" << endl;
	_QuickSort(arr, 0, arrayLength - 1);
	Display(arr, arrayLength);
}

双路快排

void _QuickSort2Ways(int* arr, int left, int right)
{
	auto partition = [=]()->int {
		int key = arr[left];
		int i = left;
		int j = right;
		while (i < j) {
			// j一直左移到小于key的位置
			while (i < j && arr[j] >= key) {
				--j;
			}
			if (i < j) {
				arr[i] = arr[j];
				++i;
			}
			// i一直右移到大于key的位置
			while (i < j && arr[i] <= key) {
				++i;
			}
			if (i < j) {
				arr[j] = arr[i];
				--j;
			}
		}
		arr[i] = key;
		return i;
	};
	if (left < right) {
		int p = partition();
		_QuickSort2Ways(arr, left, p - 1);
		_QuickSort2Ways(arr, p + 1, right);
	}
}

void QuickSort2Ways(int* arr, int arrayLenght)
{
	cout << "Quick Sort Two Ways" << endl;
	_QuickSort2Ways(arr, 0, arrayLenght - 1);
	Display(arr, arrayLenght);
}

堆排序

/*
近似完全二叉树的结构,并同时满足堆积的性质:
即子结点的键值或索引总是小于(或者大于)它的父节点
*/
void HeapSort(int* arr, int arrayLength)
{
	cout << "Heap Sort" << endl;
	auto maxHeapify = [=](int first, int last)->void {
		int root = first;
		int child = root * 2 + 1;
		while (child <= last) {
			//比较左右孩子
			if (child < last && arr[child] < arr[child + 1]) {
				++child;
			}
			if (arr[root] >= arr[child]) {
				return;
			}
			swap(arr[child], arr[root]);
			root = child;
			child = root * 2 + 1;
		}
	};
	for (int i = arrayLength / 2 - 1; i >= 0; --i) {
		maxHeapify(i, arrayLength - 1);
	}
	// 最大值与末尾元素交换
	for (int i = arrayLength - 1; i > 0; --i) {
		swap(arr[0], arr[i]);
		maxHeapify(0, i - 1);
	}

	Display(arr, arrayLength);
}

计数排序

/*
计数排序不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间
*/
void CountingSort(int* arr, int arrayLength)
{
	cout << "Counting Sort" << endl;
	int* arr2 = new int[arrayLength];
	int min = arr[0];
	int max = arr[0];
	for (int i = 0; i < arrayLength; i++) {
		if (min > arr[i]) { min = arr[i]; }
		if (max < arr[i]) { max = arr[i]; }
	}
	int countLength = max - min + 1;
	int* countArray = new int[countLength];
	memset(countArray, 0, countLength * sizeof(int));
	for (int i = 0; i < arrayLength; i++) {
		countArray[arr[i] - min]++;
	}
	for (int i = 1; i < countLength; i++) {
		countArray[i] += countArray[i - 1];
	}
	for (int i = arrayLength - 1; i >= 0; i--) {
		arr2[countArray[arr[i] - min] - 1] = arr[i];
		countArray[arr[i] - min]--;
	}
	Display(arr2, arrayLength);
	delete[] countArray;
	delete[] arr2;
}

基数排序

/*
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;
依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。
最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。
*/
void RadixSort(int* arr, int arrayLength, int System = 10)
{
	cout << "Radix Sort" << endl;
	int* arr2 = new int[arrayLength];
	int* countArray = new int[System];
	int max = arr[0];
	for (int i = 0; i < arrayLength; ++i) {
		if (max < arr[i]) { max = arr[i]; }
	}
	for (int radix = 1; radix <= max; radix *= System) {
		memset(countArray, 0, System * sizeof(int));
		for (int i = 0; i < arrayLength; ++i) {
			countArray[(arr[i] / radix) % System]++;
		}
		for (int i = 1; i < System; ++i) {
			countArray[i] += countArray[i - 1];
		}
		for (int i = arrayLength - 1; i >= 0; --i) {
			int temp = (arr[i] / radix) % System;
			arr2[countArray[temp] - 1] = arr[i];
			countArray[temp]--;
		}
		memcpy(arr, arr2, arrayLength * sizeof(int));
	}
	Display(arr, arrayLength);
	delete[] arr2;
	delete[] countArray;
}

桶排序

/*
当输入的元素是n个0到k之间的整数时,时间复杂度是O(n+k),空间复杂度也是O(n+k),
其排序速度快于任何比较排序算法。当k不是很大并且序列比较集中时,计数排序是一个很有效的排序算法。
*/
void _MergeSort(int* arr, int first, int last, int* temp)
{
	int mid = (first + last) / 2;
	auto mergeArray = [=]()->void {
		int k = 0;
		int i = first, m = mid;
		int j = mid + 1, n = last;
		while (i <= m && j <= n) {
			temp[k++] = arr[i] < arr[j] ? arr[i++] : arr[j++];
		}
		while (i <= m) {
			temp[k++] = arr[i++];
		}
		while (j <= n) {
			temp[k++] = arr[j++];
		}
		for (i = 0; i < k; ++i) {
			arr[first + i] = temp[i];
		}
	};
	if (first < last) {
		_MergeSort(arr, first, mid, temp);
		_MergeSort(arr, mid + 1, last, temp);
		mergeArray();
	}
}
void BucketSort(int* arr, int arrayLength, int System = 3)
{
	cout << "Bucket Sort" << endl;
	int* arr2 = new int[arrayLength];
	int* countArray = new int[System];
	int min = arr[0];
	int max = arr[0];
	for (int i = 0; i < arrayLength; i++) {
		if (min > arr[i]) { min = arr[i]; }
		if (max < arr[i]) { max = arr[i]; }
	}
	int step = (max - min + 1) / System;
	if (step <= 0) {
		step = 1;
		System = 1;
	}
	memset(countArray, 0, System * sizeof(int));
	for (int i = 0; i < arrayLength; ++i) {
		int index = (arr[i] - min) / step;
		index = index < System ? index : System - 1;
		countArray[index]++;
	}
	for (int i = 1; i < System; ++i) {
		countArray[i] += countArray[i - 1];
	}
	for (int i = arrayLength - 1; i >= 0; --i) {
		int index = (arr[i] - min) / step;
		index = index < System ? index : System - 1;
		arr2[countArray[index] - 1] = arr[i];
		countArray[index]--;
	}
	memcpy(arr, arr2, arrayLength * sizeof(int));
	for (int i = 0; i < System; ++i) {
		int first = countArray[i];
		int last = i == System - 1 ? arrayLength - 1 : countArray[i + 1];
		_MergeSort(arr, first, last, arr2);
	}
	Display(arr, arrayLength);
	delete[] arr2;
	delete[] countArray;
}

主函数

#include <iostream>
#include <string.h>
using namespace std;
void Display(int* arr, int arrayLength)
{
	for (int i = 0; i < arrayLength; ++i) {
		cout << arr[i] << " ";
	}
	cout << endl;
}
int main()
{
	int arr[] = { 3,2,1,1,2,5,6,4 };
	int arrayLength = sizeof(arr) / sizeof(int);
	cout << "initial array:" << endl;
	Display(arr, arrayLength);
	BubbleSort(arr, arrayLength); // 冒泡排序
	SelectSort(arr, arrayLength); // 选择排序
	InsertSort(arr, arrayLength); // 插入排序
	ShellSort(arr, arrayLength, arrayLength); // 希尔排序
	MergeSort(arr, arrayLength); // 归并排序
	QuickSort(arr, arrayLength); // 快速排序
	QuickSort2Ways(arr, arrayLength); // 双路快速排序
	HeapSort(arr, arrayLength); // 堆排序
	CountingSort(arr, arrayLength); // 计数排序
	RadixSort(arr, arrayLength); // 基数排序
	BucketSort(arr, arrayLength); // 桶排序
	return 0;
}

参考资料:https://www.cnblogs.com/onepixel/p/7674659.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值