【从头学数据结构和算法】选择排序及其优化(c++实现)

c++实现的选择排序及其优化



普通选择排序

原理

每次从为排序区间选择一个最小的数据与前面的交换。

性质

  • 时间复杂度
    ——最好、最坏和平均:O(n^2)
  • 空间复杂度
    ——O(1):原地排序
  • 稳定性
    ——不稳定!!!

代码

template<typename T> 
void select_sort0(T *a, int len) {
	// 首先检查数据的合法性(TODO 不完善).
	if (a == NULL || len <= 1) {
		return;
	}
	
	int min = 0;	// 当前待排序的数据中最小值的下标 
	int j = 0;		// 内层循环(移动数据)计数变量   
	T temp = 0;		// 用于数据交换的临时变量 
	
	// 对未排序区间进行遍历 
	for (int i = 0; i < len; ++i) {
		min = i;
		// 在未排序区间中查找最小值 
		for (j = i+1; j < len; ++j) {
			if (a[j] < a[min]) {
				// 更新最小值下标 
				min = j; 
			}
		}  
		// 数据交换 
		temp = a[i];
		a[i] = a[min];
		a[min] = temp; 
	} 
} 

优化1:一次找最大最小两值

原理

与普通的相同,只不过每次找最小和最大两值,然后交换两端的数据

性质

  • 时间复杂度
    ——最好、最坏和平均:O(n^2)【耗时是普通方法的一半左右】
  • 空间复杂度
    ——O(1):原地排序
  • 稳定性
    ——不稳定!!!

代码

template<typename T> 
void select_sort1(T *a, int len) {
	// 首先检查数据的合法性(TODO 不完善).
	if (a == NULL || len <= 1) {
		return;
	}
	
	int min = 0;	// 当前待排序的数据中最小值的下标 
	int max = 0; 	// 当前待排序的数据中最小值的下标 
	int j = 0;		// 内层循环(移动数据)计数变量
	int k = len;   	// 记录已排序空间中最大值的交换位 
	T temp = 0;		// 用于数据交换的临时变量 
	
	// 对未排序区间进行遍历 (每次更新头尾的位置)
	for (int i = 0; i < k; ++i,--k) {
		min = i;
		max = i; 
		// 在未排序区间中查找最小值和最小值 
		for (j = i+1; j < k; ++j) {
			if (a[j] < a[min]) {
				// 更新最小值下标
				min = j; 
			}
			if (a[j] > a[max]) {
				// 更新最大值下标 
				max = j;
			} 
		} 
		if (min != i) {
			// 数据交换-最小值 
			temp = a[i];
			a[i] = a[min];
			a[min] = temp; 
		} 
		if (max == i) {
			// 防止之前的已经被换掉
			max = min; 
		}
		if (max != k-1) {
			// 数据交换-最大值 
			temp = a[k-1];  
			a[k-1] = a[max];
			a[max] = temp;	
		} 
	} 
} 

测试

以20000个整数进行测试,记录时间,同时assert是否与algorithm中sort结果相同。测试代码略,可见完整代码中。
测试结果时间(同时,assert未报错)如下图所示:
![在这里插入图片描述]
可见,优化效率提升基本接近于2倍,而且选择排序本身也比冒泡排序要快(详情见【从头学数据结构和算法】冒泡排序及其优化(c++实现)(https://blog.csdn.net/ZhangDanzhu/article/details/96277870))。


完整代码

排序及优化及测试 完整代码在:
https://github.com/zhangdanzhu/basic_data-structure_algorithm/blob/master/sort/cpp/selection_sort.cpp

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值