目录
引言
大家好!今天我们将进入一个充满神奇魔力的世界——二分查找。在这个世界里,我们将用有序的字典来展开一场刺激的探险,寻找我们心仪的元素。快跟我一起来,开启二分查找的奇妙之旅吧!
代码详解
#include <stdio.h>
#define LEN 10
// global variable: file scope
// avoid using global variables as possible as you can
/**
* Search for the key in the dict.
* @param key The key to search for.
* @param dict The dictionary to search.
* @param len The length of the dict.
* @return the index of the key in the dict if found, -1 otherwise
*/
int BinarySearch(int key, const int dict[], int len);
int main() {
int dictionary[LEN] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55};
int key = 0;
scanf("%d", &key);
int index = BinarySearch(key, dictionary, LEN);
if (index == -1) {
printf("Not found!\n");
} else {
printf("The index of %d is %d.\n", key, index);
}
return 0;
}
int BinarySearch(int key, const int dict[], int len) {
int low = 0;
int high = len - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (key > dict[mid]) {
low = mid + 1;
} else if (key < dict[mid]) {
high = mid - 1;
} else {
return mid;
}
}
return -1;
}
让我们一行行地来解读这段代码吧!
- 首先,在代码开头我们定义了一个宏
LEN
,它表示字典的长度。这个宏的作用就像是在迷宫中告诉我们迷宫的尺寸,让我们可以更好地探索其中的秘密。 - 然后,我们定义了一个函数
BinarySearch
,它用于在字典中搜索特定的关键字。这个函数采用了三个参数:key
是要搜索的关键字,dict
是待搜索的有序字典,len
是字典的长度。函数的返回值是关键字在字典中的索引,如果没有找到则返回 -1。
int BinarySearch(int key, const int dict[], int len) {
int low = 0;
int high = len - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (key > dict[mid]) {
low = mid + 1;
} else if (key < dict[mid]) {
high = mid - 1;
} else {
return mid;
}
}
return -1;
}
在我们的搜索函数中,我们使用了两个变量 low
和 high
来分别标记搜索范围的最低位置和最高位置。这就像是迷宫探险中的两扇门,我们通过不断调整它们的位置,逐步缩小搜索范围,直到找到我们想要的宝藏。
我们使用了一个 while
循环来迭代搜索。在循环中,我们通过计算中间位置 mid
来确定当前搜索范围的中间元素。然后,我们将关键字与中间元素进行比较,如果大于中间元素,则将 low
更新为 mid + 1
,将搜索范围缩小到右半部分;如果小于中间元素,则将 high
更新为 mid - 1
,将搜索范围缩小到左半部分。如果关键字等于中间元素,说明我们找到了宝藏,直接返回中间元素的索引。
如果经过循环后仍然没有找到宝藏,说明字典中没有该关键字,我们返回 -1,表示未找到。
int main() {
int dictionary[LEN] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55};
int key = 0;
scanf("%d", &key);
int index = BinarySearch(key, dictionary, LEN);
if (index == -1) {
printf("Not found!\n");
} else {
printf("The index of %d is %d.\n", key, index);
}
return 0;
}
这段代码是我们的主函数。我们首先定义了一个有序字典 dictionary
,其中存储了一些数字。然后,通过 scanf
函数从用户输入中获取要搜索的关键字 key
。
接下来,我们调用了 BinarySearch
函数,并将关键字、字典及其长度作为参数传递进去。得到的返回值存储在变量 index
中。
最后,我们根据 index
的值进行判断,如果为 -1,则输出 “Not found!”,表示未找到关键字。否则,我们输出关键字在字典中的索引。
拓展内容
有序字典的奇妙之处
在本篇文章中,我们提到了字典是有序的,这是二分查找算法的前提条件之一。有序字典的优势何在呢?有序字典可以大大提高查找效率,因为我们可以通过比较关键字与中间元素的大小来确定应该继续搜索左半部分还是右半部分,从而将查找范围一次次缩小,直到找到目标元素。如果字典是无序的,我们只能进行线性搜索,效率将大大降低。
避免使用全局变量
我们在代码中看到了一个全局变量 LEN
,它被用作字典的长度。尽管在这个简单的示例中使用全局变量不会带来太大问题,但在实际开发中,过多使用全局变量可能会导致代码不易读和维护。因此,在设计程序时,我们应尽量避免使用全局变量,并且推荐将变量的作用
范围限定在需要访问它的特定代码块内部。
全局变量是在整个程序中都可以访问的变量,而局部变量则只能在其定义的代码块中使用。在前述例子中,LEN作为一个全局变量,能够在整个代码中进行访问和修改。然而,全局变量的广泛使用可能会导致代码复杂化和难以维护。
当我们在大型项目或团队中开发软件时,可能会有多个开发人员同时对代码进行修改和维护。过多使用全局变量会增加代码的耦合性,使得多个部分的代码依赖于同一个变量。这样一来,当我们需要修改全局变量时,就需要仔细考虑它可能对其他代码的影响,以免引发意想不到的错误和行为。
为了解决这个问题,我们可以尽量避免使用全局变量,并将变量的作用范围限定在需要访问它的特定代码块内部。可以使用局部变量来替代全局变量,并将其定义在需要使用的代码块中。这样一来,每个代码块都拥有特定的上下文,变量的作用范围也更加清晰明确。这种做法使得代码更容易理解和维护,并且减少了潜在的冲突和错误。
此外,在设计和开发过程中,我们还可以使用封装和模块化的原则,将代码分成各个功能模块或类。每个模块或类都可以有自己的局部变量,而不需要依赖于全局变量。这种结构化的设计可以提高代码的可读性和可维护性,而且使得代码更易于重用和扩展。
综上所述,虽然在简单的情况下使用全局变量可能不会引起太大问题,但在实际开发中,过多使用全局变量可能会导致代码难以理解和维护。因此,我们应该尽量避免使用全局变量,并通过将变量的作用范围限定在需要访问它的特定代码块内部,以提高代码的可读性、可维护性和可重用性。这样的设计原则和实践有助于构建更健壮、可靠且易于扩展的软件系统。