初识递归思想之美,一场入坑的完美盛筵_冒泡排序加强版,递归最大数、最小数及数组元素和

冒泡排序、递归算法

首先给出一种让你可能耳目一新的冒泡排序算法

void bubblesort(const int a[], const int& n){
    
    
	bool sorted = false;		// 整体排序标志,这是本算法的有力手段
	while(!sorted){
    
    
		sorted = true;			// 假定已经排序
		for(int i = 1; i < n; ++i){
    
    	// 自左向右逐对检查当前范围 a[0, n)内的各相邻元素
			if(a[i - 1] > a[i]){
    
    	// 逆序则交换
				std::swap(a[i - 1], a[i]);
				sorted = false;		// 因整体排序不能保证,需要清除排序标志位
			}
		}
		n--;	// 至此末元素必然就位,故可以缩短待排序序列的有效长度
	}
}

☆ 借助布尔型标志位 sorted,可以提前退出,而不总是蛮力地做 n - 1趟扫描交换。

下面你会看到更加强大的算法内容

考虑一个数组求和问题,一般人的算法如下

const int sum(const int* p, const int& n) {
    
    
	int sum = 0;
	for (int i = 0; i < n; ++i) {
    
    		// T(n) = σ(n)
		sum += p[i];
	}
	return sum;
}
  • 迭代求和
const int sum(int* p, int n) {
    
    
	int sumA = 0;
	while (n-- > 0) {
    
    
		sumA += p[n];
	}
	return sumA;
}

现在我们来考虑用递归求数组元素总和

  • 线性递归
const int sum(const int a[], const int& n) {
    
    
	if (1 > n) {
    
    
		return 0;
	}
	else {
    
    
		return sum(a, n - 1) + a[n - 1];
	}
}
  • 我把上述两函数放在一起(这里是函数重载,所以可以放一起)然后调用 sum 函数,调用形式(sum(a,int n))是一样的。你猜谁被编译器选择了,是下面的递归求和函数而非一般的求和函数。

再深入一点,二分递归求和

// 算法入口的调用形式 sum(a, 0, n - 1)
const int sum(const int a[], const int& l, const int& r) {
    
    
	if (l == r) {
    
    
		return a[l];
	}
	else {
    
    
		int mid = (l + r) >> 1;		// 算术右移一位,相当于除以 2
		return sum(a, l, mid) + sum(a, mid + 1, r);
	}
}

递归是不是很强大,反正我觉得很牛

由此我想到了用递归来求最大值和最小值。我试了一下,代码放下面,当然递归的方式也有多种多样,也许你也能创造不一样的精彩递归哦。

  • 线性递归求最大值
// 线性递归求最大值
inline int maxdouble(const int& a, const int& b) {
    
    
	return a > b ? a : b;
}
// 算法入口的调用形式 max(a, 0, n - 1)
const int max(const int a[], const int& l, const int& n) {
    
    
	if (n == l) {
    
    
		return a[l];
	}
	else {
    
    
		return maxdouble(max(a, l + 1, n), a[l]);
	}
}
  • 线性递归求最小值

另外一种更简化的方法

//调用形式为 min(a,0,n - 1)
const int min(const int a[], const int& l, const int& n) {
    
    
	if (l == n) {
    
    
		return a[l];
	}
	else {
    
    
		return min(a, l + 1, n) < a[l] ? min(a, l + 1, n) : a[l];
	}
}

当然,以此类推,还可以用二分递归来求最大值、最小值

☆ 但是,递归算法比较耗内存,所消耗的空间主要取决于递归深度,所以对运行速度要求极高、存储空间需要精打细算的场合,往往应将递归算法改写成等价的非递归版本。

猜你喜欢

转载自blog.csdn.net/weixin_48033173/article/details/109755651