博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
十大排序算法C++实现
阅读量:4092 次
发布时间:2019-05-25

本文共 7264 字,大约阅读时间需要 24 分钟。

1、插入排序:和玩纸牌游戏一样,抓牌时小的插在前边,后边牌往后移动

void insertSort(int* arr, int len){   if(!arr || len<2)       return;   int preIndex=0, curVal=0;   for(int i=1; i
=0 && arr[preIndex]>curVal){ arr[preIndex+1] = arr[preIndex]; preIndex--; } arr[preIndex+1] = curVal; }}

2、冒泡排序:它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。

走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成

void bubbleSort(size_t size, int* arr) {	if (!arr || size <= 1) {		return;	}	bool bComplete = false;	for (size_t i = 0; i < size; i++) {		bComplete = true;		for (size_t j = 0; j < size - i - 1; j++) {			if (arr[j] > arr[j + 1])			{				std::swap(arr[j], arr[j + 1]);				bComplete = false;			}		}		if (bComplete) {			return;		}	}}

3、选择排序:选择排序是一种简单直观的排序算法

首先,在未排序序列中找到最小(大)元素,存放到排序序列的起始位置
然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾
以此类推,直到所有元素均排序完毕

void selectSort(size_t size, int* arr) {	if (!arr || size <= 1) {		return;	}	size_t minIndex = 0;	for (size_t i = 0; i < size - 1; i++) {		minIndex = i;		for (size_t j = i + 1; j < size; j++) {			if (arr[j] < arr[minIndex]) {				minIndex = j;			}		}		std::swap(arr[i], arr[minIndex]);	}}

4、希尔排序:是简单插入排序的改进版,它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。

void shellSort(size_t size, int*arr) {	if (!arr || size <= 1) {		return;	}	size_t gap = 1;	size_t j = 0;	//固定增量变化	for (gap = size / 2; gap > 0; gap /= 2) {		for (size_t i = gap; i < size; ++i) {			//int()转换类型,避免溢出,相当于分组的插入排序			for (j = i; int(j - gap) >= 0 && arr[j - gap] > arr[j]; j -= gap) {				std::swap(arr[j - gap], arr[j]);			}		}	}}

5、归并排序

void merge(int*arr, size_t left, size_t mid, size_t right) {	int len = right - left + 1;	int *temp = new int[len];  //数组较长时请用new,不然栈空间容易溢出	size_t index = 0;	size_t i = left, j = mid + 1;	while (i <= mid && j <= right){		temp[index++] = arr[i] <= arr[j] ? arr[i++] : arr[j++]; //对两边的数组从小到大放入临时空间	}	while (i <= mid){		temp[index++] = arr[i++];//比较完后,左半边有没放进去的,直接写入	}	while (j <= right)	{		temp[index++] = arr[j++];//比较完后,右半边有没有放进去的,直接写入	}	for (int k = 0; k < len; ++k){		arr[left++] = temp[k];  //把有序的临时数组写入原来数组的起始位置	}	delete[] temp;  //释放空间	temp = NULL;  //指针置空}void divide(int* arr, size_t left, size_t right) {	//递归出口	if (left == right){		return;	}	size_t mid = (left + right) / 2; //找出区间中部的数,将数组分段	divide(arr, left, mid);//递归调用,对左边继续分段;	divide(arr, mid + 1, right);//递归调用,对左边继续分段;	merge(arr, left, mid, right); //对左右两半进行排序合并成一小段有序的数组}void mergeSort(size_t size, int* arr) {	if (!arr || size <= 1) {		return;	}	size_t left = 0, right = size - 1;	divide(arr, left, right);}

6、快速排序:每次都取数组的第一个元素作为基准元素,凡是大于这个基准元素的都放在右边,凡是小于这个基准元素的都放在它的左边。

  • 设置两个变量i,j(称为哨兵),令序列的第一个元素为基准元素。
  • i指向序列的最左边, j指向序列的最右边,j从右往左试探,i从左往右试探,直到j找到小于基准的数就停止,i找到大于基准的数就停止,交换i和j指向的两个数,j继续往左试探,i继续往右试探
  • 如果i和j相遇,则i或j上的元素与基准元素交换,一轮排序结束
  • 对基准元素两边的序列重复上述步骤
void qSort(int* arr, int left, int right) {	int i = left;	int j = right;	int temp = arr[left]; //基准元素	//递归结束条件	if (left >= right) {		return;	}	while (i != j) {		while (arr[j] >= temp && i < j) { //从右往左,找到小于基准的数			j--;		}		while (arr[i] <= temp && i < j) { //从左往右,找到大于基准的数			i++;		}		//交换i和j指向的两个数,然后继续,知道i,j相遇		if (i < j) {			std::swap(arr[i], arr[j]); 		}	}	//i和j相遇,i 或 j上的元素与基准元素交换,一轮排序结束	arr[left] = arr[i]; 	arr[i] = temp;	//再分别对两边数据递归快排	qSort(arr, left, i - 1);	qSort(arr, i + 1, right);}void quickSort(size_t size, int* arr) {	if (!arr || size <= 1) {		return;	}	qSort(arr, 0, size - 1);}

7、堆排序

//建立大堆(1、完全二叉树;2、父节点的值始终大于子节点)void heapify(int* tree, int n, int i) {	//递归结束出口	if (i >= n) {		return;	}	int left = 2 * i + 1;	int right = 2 * i + 2;	int maxIndex = i;	maxIndex = (left < n && tree[left] > tree[maxIndex]) ? left : maxIndex;	maxIndex = (right < n && tree[right] > tree[maxIndex]) ? right : maxIndex;	if (maxIndex != i) {		std::swap(tree[i], tree[maxIndex]);		heapify(tree, n, maxIndex);	}}void heapSort(int size, int* arr) {	if (!arr || size <= 1) {		return;	}	int lastNodeIndex = size - 1; //最后一个子节点	int lastParentIndex = (lastNodeIndex - 1) / 2; //最后一个子节点的父节点	//从最后一个子节点的父节点开始对所有父节点建立大堆	for (int i = lastParentIndex; i >= 0; i--){		heapify(arr, size, i);	}	//经过上一步骤处理后根节点必然是最大的值	//将根节点和最后一个子节点交换位置后截取掉树的最后一个节点,也就是最大的值,这时大堆被打乱,再对树中剩下的值heapify	for (int i = size - 1; i >= 0; i--) {		std::swap(arr[i], arr[0]);		heapify(arr, i, 0);	}}

8、计数排序

void countSort(int size, int* arr) {	if (!arr || size <= 1) {		return;	}	int index = 0, min, max;	min = max = arr[0];	//遍历数组找出最小和最大的数  5  3  4  7  2  4  3  4  7	for (size_t i = 1; i < size; i++) {		min = arr[i] < min ? arr[i] : min;		max = arr[i] > max ? arr[i] : max;	}	int len = max - min + 1;	int* temp = new int[len](); //初始化为0	for (int i = 0; i < size; i++) {		temp[arr[i] - min]++;	}	//打印下计数数组	for (int i = 0; i < len; i++)	{		std::cout << temp[i] << " ";	}	std::cout << std::endl;	for (int i = min; i <= max; i++)	{		int count = temp[i - min];		for (int j = 0; j < count; ++j)	//存放元素个数不为0的,才进入循环		{			arr[index++] = i;  //把元素值写回数组		}	}	delete[] temp;	temp = nullptr;}

9、桶排序,将数据按规则分组,对各小组再分别排序

  • 数组长度一定的,只申请一次内存,避免内存碎片化,提高效率
  •  给定桶的个数,程序运行状况在不同环境下可控
void bucketSort(size_t size, int *arr, int bucketCount = 10){	if (!arr || size <= 1) {		return;	}	int maxval = arr[0];	int minval = arr[0];	//遍历数组,找出最大最小元素	for (int i = 0; i != size; ++i)	{		maxval = maxval > arr[i] ? maxval : arr[i];		minval = minval < arr[i] ? minval : arr[i];	}	//如果最大等于最小,数组不需要排序	if (maxval == minval){		return;	}	int div = /*1000*/bucketCount; //桶的个数	int space = (maxval - minval) / div + 1; //每个桶的数值跨度,+1放大一点包住	int *numsofeachbucket = new int[div](); //开辟数组,存放每个桶内的元素个数,()初始化为0	int *endpositionofeachbucket = new int[div]();	for (size_t i = 0; i != size; ++i){		//把元素按大小分到不同的桶,并增加该桶元素个数		numsofeachbucket[(arr[i] - minval) / space]++;		endpositionofeachbucket[(arr[i] - minval) / space]++;	}	for (int i = 1; i != div; ++i){		endpositionofeachbucket[i] += endpositionofeachbucket[i - 1];		//每个桶区间的最大下标+1的值	}	int *temp = new int[size];	//开辟堆空间,存放临时数组	for (size_t i = 0; i != size; ++i){		temp[--endpositionofeachbucket[(arr[i] - minval) / space]] = arr[i];		//遍历数组,把每个元素写入对应的桶中,从每个桶的后部往前写		//--运行完成后endpositionofeachbucket[i]就是该桶的首位	}	for (size_t i = 0; i != div; ++i)	{		if (numsofeachbucket[i] > 1)	//桶元素2个或以上才排序		{			//对每个桶的数组进行快速排序(元素个数,每个桶数组首位的地址)			quickSort(numsofeachbucket[i], &temp[endpositionofeachbucket[i]]);		}	}	//对排序后的数组,写入原数组	for (size_t i = 0; i != size; ++i){		arr[i] = temp[i];	}	delete[] numsofeachbucket;	delete[] endpositionofeachbucket;	delete[] temp;	numsofeachbucket = nullptr;	endpositionofeachbucket = nullptr;	temp = nullptr;}

10、基数排序

void radix_countsort(size_t size, int *arr, int exp){	int numofeachbucket[10] = { 0 };  //十个数位,每个桶上有0个元素	for (int i = 0; i != size; ++i) {		++numofeachbucket[(arr[i] / exp) % 10];	//记录该数位上相同的元素个数	}	for (int i = 1; i < 10; ++i) {		numofeachbucket[i] += numofeachbucket[i - 1];	}	int *temp = new int[size];	for (int i = size - 1; i >= 0; --i) {		int k = (arr[i] / exp) % 10;		temp[numofeachbucket[k]] = arr[i]; //把数组放在不同的区间位置上		numofeachbucket[k]--;	}	for (int i = 0; i != size; ++i) {		arr[i] = temp[i];  //一个数位排好后,写回原数组,开始下一位数的装桶排序	}	delete[] temp;	temp = nullptr;}void radixSort(size_t size, int *arr){	if (!arr || size <= 1) {		return;	}	int max = arr[0];	//找出最大的数	for (size_t i = 0; i != size; ++i) {		max = arr[i] > max ? arr[i] : max;	}	//从最低位开始对每个数位进行排序	for (int exp = 1; max / exp > 0; exp *= 10) {		radix_countsort(size, arr, exp);	}}

 

转载地址:http://kriii.baihongyu.com/

你可能感兴趣的文章
Spring Boot构建简单的微博应用
查看>>
Spring处理表单提交
查看>>
Spring MVC异常处理
查看>>
Leetcode 1180. Count Substrings with Only One Distinct Letter [Python]
查看>>
PHP 7 的五大新特性
查看>>
php使用 memcache 来存储 session
查看>>
php实现socket(转)
查看>>
PHP底层的运行机制与原理
查看>>
深入了解php底层机制
查看>>
PHP中的stdClass 【转】
查看>>
XHProf-php轻量级的性能分析工具
查看>>
PHP7新特性 What will be in PHP 7/PHPNG
查看>>
比较strtr, str_replace和preg_replace三个函数的效率
查看>>
ubuntu 下编译PHP5.5.7问题:configure: error: freetype.h not found.
查看>>
PHP编译configure时常见错误 debian centos
查看>>
configure: error: Please reinstall the BZip2 distribution
查看>>
OpenCV gpu模块样例注释:video_reader.cpp
查看>>
【增强学习在无人驾驶中的应用】
查看>>
《python+opencv实践》四、图像特征提取与描述——29理解图像特征
查看>>
《python+opencv实践》四、图像特征提取与描述——30Harris 角点检测
查看>>