数据结构 - 迭代、递归和分治思想

栈和队列的应用

文章目录

  • 栈和队列的应用
      • 迭代-循环结构
      • 递归-选择结构:
    • 分治

迭代-循环结构

数据结构 - 迭代、递归和分治思想_第1张图片
定义

迭代(iteration):重复反馈过程的活动,每一次迭代的结果会作为下一次迭代的初始值。(A重复调用B)

迭代是一个环结构,从初始状态开始,每次迭代都遍历这个环,并更新状态,多次迭代直到到达结束状态。

实例:

斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。

形如:1 1 2 3 5 8 13 21 34 55 89...
通项公式:

 F(n) = {
   		0, 当n = 0
   		1, 当n = 1
  	 	F(n-1) + F(n-2) , 当 n > 1
 }

C语言代码实现的函数:

int main() {
    int a = 1, b = 1;
    printf("%d %d ", a, b);
    int count = 0,  t = 0;
    while(count < 10){
        t = b;
        b = a + b;
        a = t;
        printf("%d ",b);
        count++;
    }
    printf("\n");
    return 0;
}

也可以通过数组分别存储当前位和下一位,实现这个数列

递归-选择结构:

数据结构 - 迭代、递归和分治思想_第2张图片
定义

递归(recursion):递归常被用来描述以自相似方法重复事物的过程,在数学和计算机科学中,指的是在函数定义中使用函数自身的方法。(A调用A)
我们把一个直接调用自己或通过一系列的调用语句间接地调用自己的函数,称为递归函数

递归是一个树结构,从字面可以其理解为重复“递推”和“回归”的过程,当“递推”到达底部时就会开始“回归”,其过程相当于树的深度优先遍历。

注意
递归函数必须至少有一个终止条件,满足这个条件时递归不再进行,即函数不再调用自身而是返回。

根据斐波那契的通项公式,我们可以将其轻松转化为一个递归函数:

//输入序号,返回对应位置的斐波那契数
int Fibonacci(int n) {
    if(n == 0){
        return 0;
    }else if (n == 1) {
        return 1;
    }else{
        return Fibonacci(n - 1) + Fibonacci(n - 2);
    }
}

在这个函数中,n = 0和n=1是函数的两个终止条件

以树形图体现如图所示:

而对于Fib(5)的结果就是将最底层的数全部相加得到的和,我们在主函数中进行验证:

printf("%d\n", Fibonacci(5));
printf("%d\n", Fibonacci(7));

结果:

5
13

得证。

⭐️ 递归和迭代的对比

  • 使用递归能够使得程序的结构更加清晰明了、简洁、容易让人理解,从而减少读懂代码的时间
  • 但大量的递归会建立函数的副本,会消耗大量的时间和内存,而迭代不需要这种付出
  • 递归函数分为调用和回退阶段,递归的回退顺序是它调用顺序的逆序

例子2:计算N的阶乘
通项公式:

n! = {
	1 ,  n = 0
	n *  ( n  -1 ) , n > 0
}

代码:

int factorial(int n )
{
	if(0 == n) return 1;
	else return 0 * factorial( n - 1);
}

假设我们传入n的值为5,

可以看出函数递归的回退顺序是函数调用顺序的逆序

分治

当一个问题规模较大且不易求解的时候,就可以考虑将问题分为几个小的模块,逐一解决

分治思想和递归算是亲兄弟的关系,采用分治思想处理问题,使其各个小模块与大模块有相同的结构,这种特性也使递归技术有了用武之地。

例子:折半查找(二分法)算法

二分法查找针对的是一个有序的数据集合,每次通过与区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为0

二分查找非常高效,假设数据大小是n,每次查找后数据都会缩小为原来的一半,也就是会除以2,最坏情况下,直到查找区间被缩小为空,才停止

时间复杂度O(logn))

数据结构 - 迭代、递归和分治思想_第3张图片
(1)迭代实现

/**
 * 二分法-迭代实现
 * @return
 */
int BinarySerach(int a[], int value) {
    int low = 0;
    int high = 9;
    int len = 10;
    int mid;
    while (low <= high) { //确保位置合理
        mid = (low + high) / 2;
        if (a[mid] < value) {
            //右侧侧
            low = mid + 1;
        } else if (a[mid] == value) {
            return mid;
        } else {
            //左侧
            high = mid - 1;
        }
    }
    return -1; //未找到
}

int main() {
    int a[] = {3, 5, 9, 11, 22, 35, 46, 57, 68, 71}; //有序序列
    int x = 0, loc = 0;
    printf("请输入要查找的元素:\n");
    scanf("%d", &x);
    loc = BinarySerach(a, x);
    printf("位置在:%d\n", loc);
    return 0;
}

(2)递归实现

/**
 * 二分法-递归实现
 *
 */
int BinarySerach(int a[], int value, int low, int high) {
    if (low <= high) {
        int mid = (low + high) / 2;
        if (a[mid] < value) {
            //右侧
            return BinarySerach(a, value, mid + 1, high);
        } else if (a[mid] == value) {
            return mid;
        } else {
            //左侧
            return BinarySerach(a, value, low, high - 1);
        }
    } else {
        return -1; //查无此人
    }
}
int main() {
    int a[] = {3, 5, 9, 11, 22, 35, 46, 57, 68, 71}; //有序序列
    int x = 0, loc = 0;
    int low = 0, hight = 9;
    printf("请输入要查找的元素:\n");
    scanf("%d", &x);
    loc = BinarySerach(a, x, 0, 9);
    printf("位置在:%d\n", loc);
    return 0;
}

效果:

请输入要查找的元素:
3
位置在:0
请输入要查找的元素:
71
位置在:9
请输入要查找的元素:
22
位置在:4
请输入要查找的元素:
101
位置在:-1

你可能感兴趣的:(计算机基础,二分法,数据结构,算法)