「数组」十大排序:精讲与分析(C++)

news2024/11/15 13:49:47

概述

截止目前,我们已经讲解并分析了十种最常见的排序算法,下附对应文章链接和全体Code。

链接

「数组」冒泡排序|选择排序|插入排序 / 及优化方案(C++)

「数组」归并排序 / if语句优化|小区间插入优化(C++)

「数组」快速排序 / 随机值优化|小区间插入优化(C++)

「数组」堆排序 / 大根堆优化(C++)

「数组」希尔排序 / 区间增量优化(C++)

「数组」计数排序|桶排序|基数排序(C++)

Code

#pragma once
using namespace std;
void show(int arr[], int len) {
	for (int i = 0; i < len; i++)
		cout << arr[i] << ' ';
	cout << endl;
}
void swap(int& a, int& b) {
	int temp = b;
	b = a, a = temp;
}
//冒泡排序
void bubble_sort(int arr[], int len) {
	while (len--) {
		for (int i = 0; i < len; i++) {
			if (arr[i + 1] < arr[i])
				swap(arr[i + 1], arr[i]);
		}
	}
}
void bubble_sort_pro(int arr[], int len) {
	bool flag = true;
	while (len-- && flag) {
		flag = false;
		for (int i = 0; i < len; i++) {
			if (arr[i + 1] < arr[i]) {
				swap(arr[i + 1], arr[i]);
				flag = true;
			}
		}
	}
}
//选择排序
void selection_sort(int arr[], int len) {
	for (int i = 0; i < len ; i++) {
		int min = i;
		for (int j = i + 1; j < len ; j++) 
			if (arr[j] < arr[min])min = j;
		swap(arr[i], arr[min]);
	}
}
void selection_sort_pro(int arr[], int len) {
	for (int i = 0; i <= len / 2; i++) {
		int min = i, max = i,j;
		for (j = i + 1; j < len - i; j++) {
			if (arr[j] < arr[min])min = j;
			if (arr[j] > arr[max])max = j;
		}
		if (max==i)max = min;
		swap(arr[i], arr[min]); 
		swap(arr[len - i - 1], arr[max]); 
	}
}
//插入排序
void insertion_sort(int arr[], int len) {
	for (int i = 1; i < len; i++) {
		int temp = arr[i], j = i - 1;
		for (; j >=0; j--) {
			if (temp<arr[j])arr[j + 1] = arr[j];
			else break;
		}
		arr[j+1] = temp;
	}
}
void insertion_sort_pro(int arr[], int len) {
	for (int i = 1; i < len; i++) {
		int temp = arr[i], j = i - 1;
		int l = -1, r = i;
		while (l + 1 != r) {
			int mid = (l + r) / 2;
			if (arr[mid] >arr[i])r = mid;
			else l = mid;
		}
		for (; j >=r; j--)arr[j + 1] = arr[j];
		arr[j+1] = temp;
	}
}
//归并排序(分治)
void merge(int arr[], int l, int m, int r, int assist[]) {
	memcpy(&assist[l], &arr[l], sizeof(int) * (r - l));
	int i, j, k;
	for (i = l, j = m, k = l;; k++) {
		if (i == m || j == r)break;
		if (assist[i] <= assist[j])arr[k] = assist[i++];
		else arr[k] = assist[j++];
	}
	while (i != m)arr[k++] = assist[i++];
	while (j != r)arr[k++] = assist[j++];
}
void recursion(int arr[], int l, int r, int assist[]) {
	if (r - l <= 1)return;
	int m = (l + r) / 2;
	recursion(arr, l, m, assist);
	recursion(arr, m, r, assist);
	merge(arr, l, m, r, assist);
}
void merge_sort(int arr[], int len) {
	int* assist = new int[len];
	recursion(arr, 0, len, assist);
	delete[] assist;
}
void merge_if(int arr[], int l, int m, int r, int assist[]) {
	if (arr[m - 1] <= arr[m])return;
	memcpy(&assist[l], &arr[l], sizeof(int) * (r - l));
	int i, j, k;
	for (i = l, j = m, k = l;; k++) {
		if (i == m || j == r)break;
		if (assist[i] <= assist[j])arr[k] = assist[i++];
		else arr[k] = assist[j++];
	}
	while (i != m)arr[k++] = assist[i++];
	while (j != r)arr[k++] = assist[j++];
}
void recursion_with_insertion(int arr[], int l, int r, int assist[]) {
	if (r - l <= 20) {
		insertion_sort(&arr[l], r - l);
		return;
	}
	int m = (l + r) / 2;
	recursion_with_insertion(arr, l, m, assist);
	recursion_with_insertion(arr, m, r, assist);
	merge_if(arr, l, m, r, assist);
}
void MGsort(int arr[], int len) {
	int* assist = new int[len];
	recursion_with_insertion(arr, 0, len, assist);
	delete[] assist;
}
//快速排序(冒泡+分治)
int partition(int arr[], int l, int r) {
	swap(arr[l], arr[r-1]);
	int i, j;
	for (i = l, j = l; j <= r - 1; j++) 
		if (arr[j] <= arr[r - 1])swap(arr[i++], arr[j]);
	return i-1;
}
void quick_sort(int arr[], int l,int r) {
	if (r-l<=1)return ;
	int pos = partition(arr, l, r);
	quick_sort(arr, l, pos);
	quick_sort(arr, pos + 1, r);
}
#include <random>
mt19937 mt;
int random_partition(int arr[], int l, int r) {
	int pos = mt() % (r - l) + l;
	swap(arr[pos], arr[r - 1]);
	int i, j;
	for (i = l, j = l; j <= r - 1; j++)
		if (arr[j] <= arr[r - 1])swap(arr[i++], arr[j]);
	return i - 1;
}
void QKsort(int arr[], int l, int r) {
	if (r - l <= 20) {
		insertion_sort(&arr[l],r-l); 
		return;
	}
	int pos = random_partition(arr, l, r);
	QKsort(arr, l, pos);
	QKsort(arr, pos + 1, r);
}
//堆排序(选择+分治)
#define father(x) ((x-1)/2)
#define lchild(x) (2*x+1)
#define rchild(x) (2*x+2)
void up(int arr[], int idx) {
	if (idx && arr[father(idx)] > arr[idx]) {
		swap(arr[father(idx)], arr[idx]);
		up(arr, father(idx));
	}
}
void down(int arr[], int idx, int size) {
	int pos;
	if (rchild(idx) < size)pos = arr[lchild(idx)] < arr[rchild(idx)] ? lchild(idx) : rchild(idx);
	else if (lchild(idx) < size)pos = lchild(idx);
	else return;
	if (arr[idx] > arr[pos]) {
		swap(arr[idx], arr[pos]);
		down(arr,pos,size);
	}
}
void heap_sort(int arr[], int len) {
	int size = 0;
	for (int i = 0; i < len; i++) {
		up(arr, i);
		size++;
	}
	int* assist = new int[len];
	for (int j = 0; j < len; j++) {
		assist[j] = arr[0];
		arr[0] = arr[--size];
		down(arr,0,size);
	}
	memcpy(arr, assist, sizeof(int) * len);
	delete[] assist;
}
void bigger_up(int arr[], int idx) {
	if (idx && arr[father(idx)] < arr[idx]) {
		swap(arr[father(idx)], arr[idx]);
		bigger_up(arr, father(idx));
	}
}
void smaller_down(int arr[], int idx, int size) {
	int pos;
	if (rchild(idx) < size)pos = arr[lchild(idx)] > arr[rchild(idx)] ? lchild(idx) : rchild(idx);
	else if (lchild(idx) < size)pos = lchild(idx);
	else return;
	if (arr[idx] < arr[pos]) {
		swap(arr[idx], arr[pos]);
		smaller_down(arr, pos, size);
	}
}
void HPsort(int arr[], int len) {
	int size = 0;
	for (int i = 0; i < len; i++,size++) 
		bigger_up(arr, i);
	while (size--) {
		swap(arr[0], arr[size]);
		smaller_down(arr, 0, size);
	}
}
//希尔排序(插入+分治)
void shell_sort(int arr[], int len) {
	int d = len;
	while (d /= 2) {
		for (int group = 0; group < d; group++) {
			for (int i = group+d; i < len; i += d) {
				int temp = arr[i], j = i - d;
				for (; j >= 0; j -= d) {
					if (temp < arr[j])arr[j + d] = arr[j];
					else break;
				}
				arr[j + d] = temp;
			}
		}
	}
}
void SLsort(int arr[], int len) {
	int d = len;
	while (d=d/3+1) {
		for (int group = 0; group < d; group++) {
			for (int i = group + d; i < len; i += d) {
				int temp = arr[i], j = i - d;
				for (; j >= 0; j -= d) {
					if (temp < arr[j])arr[j + d] = arr[j];
					else break;
				}
				arr[j + d] = temp;
			}
		}
		if (d == 1)break;
	}
}
//计数排序(基础非比较排序)
#include <algorithm>
void count_sort(int arr[], int len) {
	int size = *max_element(arr, arr + len) + 1;
	int* cnt=new int[size]();
	for (int i = 0; i < len; i++)cnt[arr[i]]++;
	for (int j = 0, k = 0; j < size; j++)
		while(cnt[j])arr[k++] = cnt[j]--;
	delete[] cnt;
}
//桶排序(大范围非比较+小区间比较排序)
#include <algorithm>
#include <vector>
void bucket_sort(int arr[], int len) {
	using bucket = vector<int>;
	int max_limit = *max_element(arr, arr + len);
	int min_limit = *min_element(arr, arr + len);
	int num_of_buckets = (max_limit - min_limit) / len + 1;
	int size_of_bucket = (max_limit - min_limit) / num_of_buckets + 1;
	vector<bucket>buckets(num_of_buckets);
	for (int i = 0; i < len; i++)buckets[(arr[i] - min_limit) / size_of_bucket].push_back(arr[i]);
	for (bucket& b : buckets)insertion_sort(b.data(), b.size());
	int k = 0;
	for (const bucket& b : buckets) {
		memcpy(arr + k, b.data(), b.size() * sizeof(int));
		k += b.size();
	}
}
//基数排序(整数数位非比较排序)
#include <algorithm>
#include <vector>
void radix_sort(int arr[], int len) {
	using bucket = vector<int>;
	bucket buckets[10];
	int limit = *max_element(arr, arr + len);
	for(int mask=1;mask<limit;mask*=10){
		for (int i = 0; i < len; i++)buckets[arr[i] / mask % 10].push_back(arr[i]);
		for (int j = 0, k = 0; j < 10; j++) {
			memcpy(arr + k, buckets[j].data(), buckets[j].size() * sizeof(int));
			k += buckets[j].size();
			buckets[j].clear();
		}
	}
}

测试Code

#include <iostream>
#include <Windows.h>
#include "sort.h"
int main()
{
	int nums = 500000;
	int* arr1 = new int[nums];
	int* arr2 = new int[nums];
	DWORD tick1, tick2;
 	for (int i = 0; i < nums; i++) {
		int x = mt() % 100000000;
		arr1[i] =arr2[i]= x;
	}
	cout << "________________________________________________________________________________" << endl;
	cout << "                              data num : "<< nums << endl;
	cout << "________________________________________________________________________________" << endl;
	cout << "|         index          |          name          |          time(ms)          "  << endl;
	cout << "________________________________________________________________________________" << endl;

	tick1 = GetTickCount64();
	bubble_sort_pro(arr1, nums);//show(arr1, nums);
    tick2 = GetTickCount64();
	cout << "|            1           |       bubble sort      |         " << tick2 - tick1 << endl;
	memcpy(arr1, arr2, sizeof(int) * nums);

	tick1 = GetTickCount64();
	selection_sort_pro(arr1, nums);//show(arr1, nums);
	tick2 = GetTickCount64();
	cout << "|            2           |     selection sort     |         " << tick2 - tick1 << endl;
	memcpy(arr1, arr2, sizeof(int) * nums);

	tick1 = GetTickCount64();
	insertion_sort(arr1, nums);//show(arr1, nums);
	tick2 = GetTickCount64();
	cout << "|            3           |     insertion sort     |         " << tick2 - tick1 << endl;
	memcpy(arr1, arr2, sizeof(int) * nums);

	tick1 = GetTickCount64();
	MGsort(arr1, nums);//show(arr1, nums);
	tick2 = GetTickCount64();
	cout << "|            4           |       merge sort       |         " << tick2 - tick1 << endl;
	memcpy(arr1, arr2, sizeof(int) * nums);

	tick1 = GetTickCount64();
	QKsort(arr1,0,nums);//show(arr1, nums);
	tick2 = GetTickCount64();
	cout << "|            5           |       quick sort       |         " << tick2 - tick1 << endl;
	memcpy(arr1, arr2, sizeof(int) * nums);

	tick1 = GetTickCount64();
	HPsort(arr1, nums);//show(arr1, nums);
	tick2 = GetTickCount64();
	cout << "|            6           |       heap sort        |         " << tick2 - tick1 << endl;
	memcpy(arr1, arr2, sizeof(int) * nums);

	tick1 = GetTickCount64();
	SLsort(arr1, nums);//show(arr1, nums);
	tick2 = GetTickCount64();
	cout << "|            7           |       shell sort       |         " << tick2 - tick1 << endl;
	memcpy(arr1, arr2, sizeof(int) * nums);

	tick1 = GetTickCount64();
	count_sort(arr1, nums);//show(arr1, nums);
	tick2 = GetTickCount64();
	cout << "|            8           |       count sort       |         " << tick2 - tick1 << endl;
	memcpy(arr1, arr2, sizeof(int) * nums);

	tick1 = GetTickCount64();
	bucket_sort(arr1, nums);//show(arr1, nums);
	tick2 = GetTickCount64();
	cout << "|            8           |       bucket sort      |         " << tick2 - tick1 << endl;
	memcpy(arr1, arr2, sizeof(int) * nums);

	tick1 = GetTickCount64();
	radix_sort(arr1, nums);//show(arr1, nums);
	tick2 = GetTickCount64();
	cout << "|            8           |       radidx sort      |         " << tick2 - tick1 << endl;
	memcpy(arr1, arr2, sizeof(int) * nums);

	cout << "________________________________________________________________________________" << endl;
	delete[] arr1;
	delete[] arr2;
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2138317.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Jlink给AT32下载程序

点击下载之后选择target device&#xff0c;这里我使用的是AT32F403ACGT7&#xff0c;M4内核&#xff0c;就选择Cortex-M4. 如果已经选过了&#xff0c;但不知道选没选对&#xff0c;就把ini文件删除即可再次进行选择。 我这里使用SW接线方式&#xff0c;选好后立马识别出来了…

Java【集合】

一、集合的概述 集合建立在数组基础上&#xff0c;主要位于java.util包中&#xff0c;用来存储Java类对象&#xff0c;并且可以实现各种数据结构。 集合大小可以改变&#xff0c;可以存放不同数据类型数据。集合不能存放基本类型数据&#xff0c;只能存放引用数据类型数据。集…

浅谈树型结构——树

文章目录 一、什么是树&#xff1f;二、树的特点三、树的概念四、树的表示形式五、树的应用 一、什么是树&#xff1f; 树是一种 非线性 的数据结构&#xff0c;是树型结构。是一个由n个有限结点组成的一个具有层次关系的集合&#xff0c;这种集合因为看起来像一颗倒挂的树&am…

测试-Gatling 与性能测试

Gatling 与性能测试详解 一、什么是性能测试&#xff1f; 性能测试是一种软件测试类型&#xff0c;旨在评估系统在负载下的响应时间、吞吐量和资源利用率等性能指标。通过性能测试&#xff0c;开发者和运维团队能够识别出系统的瓶颈、优化系统性能&#xff0c;并确保其在实际…

鸿蒙之Hello Word 遇坑总结 mac系统 不能预览 提示 Only files in a module can be previewed 解决办法

顺时代&#xff0c; 应潮流 &#xff01;鸿蒙崛起不可阻挡&#xff0c; 鸿蒙开发大有可为&#xff0c; 万丈高楼平地起&#xff0c;学编程的第一步当然是Hello World起&#xff0c;请看 第一步是下载 编辑器&#xff0c;直接官网 文档中心下载对应的系统版本安装&#xff0c;…

用nginx-rtmp-win32-master及ffmpeg模拟rtmp视频流

效果 使用nginx-rtmp-win32-master搭建RTMP服务 双击exe就可以了。切记整个目录不能有中文 README.md ,启用后本地的RTM路径: rtmp://192.168.1.186/live/xxx ffmpeg将地本地视频推RMTP F:\rtsp\ffmpeg-7.0.2-essentials_build\bin>ffmpeg -re -i F:\rtsp\123.mp4 -c c…

Java设计模式—面向对象设计原则(六) ----->合成复用原则(CRP) (完整详解,附有代码+案例)

文章目录 3.6 合成复用原则(CRP)3.6.1 概述3.6.2 案列 3.6 合成复用原则(CRP) 合成复用原则(CRP)&#xff1a;Composite Reuse Principle&#xff0c;CRP 又叫&#xff1a; 组合/聚合复用原则&#xff08;Composition/Aggregate Reuse Principle&#xff0c;CARP&#xff09;…

FastAPI 应用安全加固:HTTPSRedirectMiddleware 中间件全解析

在当今的网络环境中&#xff0c;数据安全变得越来越重要。HTTPS 作为一种安全协议&#xff0c;它通过加密传输数据来保护用户信息免受窃取和篡改。在 FastAPI 应用中&#xff0c;确保所有的 HTTP 请求都通过 HTTPS 进行是至关重要的。 中间件在 FastAPI 中用于处理请求前后的…

探索 Electron:助力文档操作应用快速落地

Electron是一个开源的桌面应用程序开发框架&#xff0c;它允许开发者使用Web技术&#xff08;如 HTML、CSS 和 JavaScript&#xff09;构建跨平台的桌面应用程序&#xff0c;它的出现极大地简化了桌面应用程序的开发流程&#xff0c;让更多的开发者能够利用已有的 Web 开发技能…

智慧农业数据集(一)

目录 葡萄叶片病虫害害数据集 茄子果实病虫害数据集 81类水果数据集 小麦叶片病虫害数据集 番茄叶片病害数据集 草莓叶片病虫害数据集 水稻叶片病虫害数据集 菠萝成熟度数据集 10类水果数据集 葡萄叶片病虫害害数据集 数据集下载链接&#xff1a;葡萄叶片病虫害数据集…

几分钟学会搭建一个自己的外卖霸王餐系统

大家好&#xff0c;我是鲸天科技千千&#xff0c;大家都知道我是做小程序开发的&#xff0c;平时会给大家分享一些互联网相关的创业项目&#xff0c;感兴趣的可以跟我关注一下。 搭建一个首先就是要搭建一个自己的霸王餐小程序&#xff0c;我们自己的工作就是把这个小程序推广…

H5 CSS布局样式定位position

1. H5 H5 CSS布局样式定位position 布局是html中非常重要的一部分&#xff0c;而定位在页面布局中也是使用频率很高的方法&#xff0c;本章节为定位在布局中的使用技巧和注意事项。   position定位有4个属性&#xff0c;分别是static(默认&#xff09;&#xff0c;absolute&a…

6芯7芯可旋转电连接器航空插头

概述 可旋转电航空插头是一种能够在旋转或相对运动的部件间稳定传输电气信号或电源的装置&#xff0c;广泛应用于航空航天、自动化设备、医疗设备等多个领域。它的核心在于精密的接触系统&#xff0c;由旋转端和固定端两部分组成&#xff0c;通过金属触点或导电环实现电气连接。…

pyflink 安装和测试

FPY Warning! 安装 apache-Flink # pip install apache-Flink -i https://pypi.tuna.tsinghua.edu.cn/simple/ Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple/ Collecting apache-FlinkDownloading https://pypi.tuna.tsinghua.edu.cn/packages/7f/a3/ad502…

华为CNA VRM搭建(使用vmware worfstartion搭建)

创建虚拟机&#xff1a; 自定义→高级 选择硬件兼容性&#xff1a;默认安装版本&#xff0c;如果未来想要将此虚拟机安装到其他电脑&#xff0c;其他电脑版本过低&#xff0c;此时可以向下兼容&#xff0c;这里我们默认版本 稍后安装操作系统&#xff1a; CNA采用Euler OS系统…

合肥鲸天科技的外卖会员卡系统有人做过吗?赚钱吗?

我们先来了解一下这个合肥鲸天科技&#xff0c;通过我在网上找到的资料和企业查询&#xff0c;这家公司还是很有实力的&#xff0c;合肥鲸天科技有限公司也是欢迎有合作的人到公司来进行一个考察和合作其他一些项目的。 外卖会员卡简介绍&#xff1a; 这个外卖会员卡&#xf…

先框架后历元还是先历元后框架?

最近测绘同行高总发现了一个问题&#xff0c;《CH/T 2014-2016 大地测量控制点坐标转换技术规范》中”5.1.4.1 a) 不同ITRF间框架转换参数的历元归算“中历元不明确&#xff0c;不知是观测历元还是目标历元。他和一些同行用一些数据测试验证后认为观测历元更为贴合实际。 ​编…

lftools frida调试小工具

前言 这两天在分析mac程序数据 &#xff0c;偶尔翻到了以前写的frida代码&#xff0c;如下 那个时候刚刚接触frida 调试Mac电脑上的程序&#xff0c;通过tcp转发到自己写的分析数据的工具上…(专门研究了一下Python的异步编程&#xff0c;libuv啥的…&#xff09; 每隔那么久…

21:I2C三:MPU6050的使用

MPU6050的使用 1、MPU6050简介1.1&#xff1a;加速度与姿态测量1.2&#xff1a;陀螺仪与姿态测量1.3&#xff1a;MPU6050内部结构1.4&#xff1a;模块内部寄存器 2、程序模拟I2C读写MPU60502.1&#xff1a;数据的读取2.2&#xff1a;转换为角度并进行融合 3、片上外设I2C2读写M…

支付域——聚合支付设计

摘要 聚合支付是支付行业的一项重要创新&#xff0c;通过整合多种支付方式&#xff0c;极大简化了支付流程&#xff0c;提升了交易效率&#xff0c;为商户和消费者提供了更加便捷的支付体验。随着移动支付的普及&#xff0c;聚合支付在未来的支付场景中将继续发挥重要作用&…