C语言数据结构中二分查找递归非递归实现并分析

C语言数据结构中二分查找递归及非递归实现

二分查找基本原理

二分查找(Binary Search)是一种基于比较目标值和中间元素的教科书式算法。每次查找都将查找范围缩小一半,直到找到目标值为止,或发现查找范围已经为空。

二分查找前提条件

在使用二分查找之前,我们需要满足以下两个前提条件:

  • 数组必须是有序的。
  • 数组需要支持随机访问,也就是支持索引。

二分查找的两种方法

在C语言中,我们通常使用两种方式实现二分查找:递归和非递归。

递归方法实现二分查找

递归实现二分查找通常需要定义一个辅助函数,如下所示:

#include <stdio.h>

int binaryRecursiveSearch(int *arr, int low, int high, int target) {
    if (low > high) {
        return -1;
    }
    int middle = (low + high) / 2;
    if (arr[middle] == target) {
        return middle;
    }
    if (arr[middle] > target) {
        return binaryRecursiveSearch(arr, low, middle - 1, target);
    } else {
        return binaryRecursiveSearch(arr, middle + 1, high, target);
    }
}

int main() {
    int arr[] = {1, 3, 5, 7, 9, 11, 13};
    int length = sizeof(arr) / sizeof(int);
    int target = 11;
    int index = binaryRecursiveSearch(arr, 0, length - 1, target);
    printf("Target %d is located at %d.\n", target, index);
    return 0;
}

在上述代码中,binaryRecursiveSearch 函数是一个递归函数,接收四个参数:

  • arr表示要查找的数组;
  • low表示数组范围的最小索引;
  • high表示数组范围的最大索引;
  • target表示要查找的目标元素。

首先,函数会计算出数组范围的中间索引,并将其保存在 middle 变量中。接着,如果 arr[middle] == target,则说明目标元素就是这个中间元素,直接返回 middle。如果 arr[middle] > target,则说明目标元素在数组范围的左半部分,于是递归调用 binaryRecursiveSearch(arr, low, middle - 1, target);否则,目标元素就在数组范围的右半部分,递归调用 binaryRecursiveSearch(arr, middle + 1, high, target)。如果递归到数组范围为空,即 low > high,则返回 -1 表示未找到目标元素。

我们可以将上述函数调用一个示例,如下所示:

int arr[] = {1, 3, 5, 7, 9, 11, 13};
int length = sizeof(arr) / sizeof(int);
int target = 11;
int index = binaryRecursiveSearch(arr, 0, length - 1, target);
printf("Target %d is located at %d.\n", target, index);

在上述代码中,我们先定义一个有序的数组 arr,然后计算出数组的长度 length 和要查找的目标元素 target。最后,我们调用递归函数 binaryRecursiveSearch(arr, 0, length - 1, target),找到目标元素在数组中的索引。

非递归方法实现二分查找

非递归方式实现二分查找相较于递归方式略显繁琐,但却可以避免函数调用栈大小不断增长的问题,同时也可以节省时间。

非递归方式实现二分查找示例代码如下:

#include <stdio.h>

int binaryIterativeSearch(int *arr, int size, int target) {
    int left = 0;
    int right = size - 1;
    while (left <= right) {
        int middle = (left + right) / 2;
        if (arr[middle] == target) {
            return middle;
        } else if (arr[middle] > target) {
            right = middle - 1;
        } else {
            left = middle + 1;
        }
    }
    return -1;
}

int main() {
    int arr[] = {1, 3, 5, 7, 9, 11, 13};
    int length = sizeof(arr) / sizeof(int);
    int target = 11;
    int index = binaryIterativeSearch(arr, length, target);
    printf("Target %d is located at %d.\n", target, index);
    return 0;
}

在上述代码中,我们定义了一个名为 binaryIterativeSearch 的函数。与递归方式不同,迭代式查找需要三个参数:

  • arr 表示要查找的数组;
  • size 表示数组的长度;
  • target 表示要查找的目标元素。

函数中,我们首先定义了两个变量 leftright,分别用于表示数组的最小索引和最大索引。通过不断缩小范围,最终找到目标元素或返回 -1 表示未找到。具体实现如下:

  • 每次找到中间元素 middle = (left + right) / 2
  • 如果 arr[middle] == target,直接返回 middle
  • 如果 arr[middle] > target,说明要查找的元素在数组的左半部分,于是右边界 right 变成了 middle - 1
  • 如果 arr[middle] < target,说明要查找的元素在数组的右半部分,于是左边界 left 变成了 middle + 1
  • 不断缩小范围,直到找到或未找到。

我们可以通过一个示例代码来演示非递归方式实现二分查找:

int arr[] = {1, 3, 5, 7, 9, 11, 13};
int length = sizeof(arr) / sizeof(int);
int target = 11;
int index = binaryIterativeSearch(arr, length, target);
printf("Target %d is located at %d.\n", target, index);

在上述代码中,我们先定义一个有序的数组 arr,然后计算出数组的长度 length 和要查找的目标元素 target。最后,我们调用非递归函数 binaryIterativeSearch(arr, length, target),找到目标元素在数组中的索引。

总结

本文演示了C语言数据结构中二分查找的递归和非递归两种实现方式,并且讲解了二分查找的基本原理和前提条件,希望对读者掌握二分查找有所帮助。

示例说明

  1. 递归实现二分查找

在示例中,定义一个有序的数组 arr,然后计算出数组的长度 length 和要查找的目标元素 target。最后,调用递归函数 binaryRecursiveSearch(arr, 0, length - 1, target),找到目标元素在数组中的索引。

  1. 非递归实现二分查找

在示例中,定义一个有序的数组 arr,然后计算出数组的长度 length 和要查找的目标元素 target。最后,调用非递归函数 binaryIterativeSearch(arr, length, target),找到目标元素在数组中的索引。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构中二分查找递归非递归实现并分析 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • midori浏览器

    以下是“Midori浏览器”的完整攻略: Midori浏览器 Midori是一款轻量级的开源Web浏览器,它专注于提供快速简单和易于使用的浏览体验。以下是Midori浏览器的详细步骤: 1. 下载和安装Midori浏览器 首先,您需要下载和安装Midori览器。您可以在Midori官方网站上找到最新版本的Midori浏览器,并根据您的操作系统下载相应的版本。…

    other 2023年5月7日
    00
  • Vue中自定义标签及其使用方式

    我们来详细讲解一下“Vue中自定义标签及其使用方式”的完整攻略。 什么是自定义标签? 在Vue中,我们可以通过注册全局或局部组件来自定义标签。自定义标签实际上就是自定义组件,我们可以通过使用这些自定义标签快速构建页面。 如何注册全局组件? 通过Vue.component(tagName, options)方法可以创建一个全局组件。其中tagName为组件名称…

    other 2023年6月25日
    00
  • fastjson使用TypeReference示例

    Fastjson使用TypeReference示例 Fastjson是一个用于Java语言的JSON解析库,支持JavaBean的序列化和反序列化,并提供了丰富的JSON处理工具。 在Fastjson中,我们经常需要使用TypeReference来获取泛型的类型信息。本文将介绍如何使用TypeReference来实现复杂类型的JSON序列化和反序列化。 JS…

    其他 2023年3月28日
    00
  • jQuery简单实现禁用右键菜单

    当我们需要禁用网页上的右键菜单时,可以使用jQuery来实现这一功能。下面是使用jQuery简单实现禁用右键菜单的完整攻略: 1. 在HTML文件中引入jQuery库文件 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <tit…

    other 2023年6月27日
    00
  • Win10键盘大小写切换怎么设置有声音?

    当你在使用Windows 10操作系统时,你可以通过以下步骤设置键盘大小写切换时的声音: 打开“设置”:点击任务栏上的“开始”按钮,然后点击“设置”图标(齿轮状图标)。 进入“时间和语言”设置:在“设置”窗口中,点击“时间和语言”选项。 进入“区域和语言”设置:在“时间和语言”窗口中,点击左侧导航栏中的“区域和语言”选项。 打开“语言首选项”:在“区域和语言…

    other 2023年8月16日
    00
  • Java进阶核心之InputStream流深入讲解

    Java进阶核心之InputStream流深入讲解 在Java中,InputStream是用于读取数据的抽象基类,使用InputStream可以从各种不同的数据源中读取数据,比如文件、网络连接等等。本文将深入讲解InputStream流的使用方法和注意事项。 常用的InputStream子类 Java中常用的InputStream子类有以下几种: FileI…

    other 2023年6月26日
    00
  • 消息提示插件toastr.js与messenger组件

    消息提示插件toastr.js与messenger组件 在网站开发中,消息提示是一个不可或缺的功能,可以使得用户快速了解网站的反馈信息和操作结果。而通过使用第三方的消息提示插件,可以实现更加美观、实用和易于管理的消息提示体验,其中toastr.js和messenger组件就是比较受欢迎的选择。 toastr.js toastr.js是一款轻量级、简单易用的J…

    其他 2023年3月29日
    00
  • 使用MockMvc进行controller层单元测试 事务自动回滚的完整案例

    以下是关于使用MockMvc进行controller层单元测试的完整攻略,包含两个示例说明: 1. 添加依赖 首先,您需要在项目的pom.xml文件中添加MockMvc和JUnit的依赖。示例: <dependencies> <!– 添加MockMvc依赖 –> <dependency> <groupId>…

    other 2023年10月19日
    00
合作推广
合作推广
分享本页
返回顶部