📜  仅查找列表目录 - C 编程语言(1)

📅  最后修改于: 2023-12-03 15:21:51.596000             🧑  作者: Mango

仅查找列表目录 - C 编程语言

在 C 编程语言中,查找列表中的某个项是否存在是一个很常见的任务。如果列表是无序的,我们需要遍历整个列表来查找目标项。这种方法的时间复杂度是 O(n),其中 n 是列表的长度。

然而,如果列表是有序的,我们就可以采用更高效的算法来查找目标项。这种方法的时间复杂度是 O(log n)。

以下是一些常见的有序列表查找算法:

二分查找

二分查找也被称为折半查找。它是一种非常基本的查找算法,能够快速地在有序列表中查找目标项。

算法的基本思想是:首先找到中间项,然后将目标项与中间项进行比较。如果它们相等,则找到了目标项;否则,如果目标项较小,则在前半部分继续查找;如果目标项较大,则在后半部分继续查找。每一次比较都将列表的长度减半。

下面是一个使用二分查找来查找整数 x 是否出现在有序列表 a 中的示例代码:

int binary_search(int a[], int n, int x) {
    int left = 0, right = n - 1;
    while (left <= right) {
        int mid = (left + right) / 2;
        if (a[mid] == x) {
            return mid;
        } else if (a[mid] < x) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;
}

时间复杂度的计算方式是基于这样一个事实:在每次循环中,列表的长度都会减半。因此,最坏情况下需要比较的次数就是 log2(n),其中 n 是列表的长度。

插值查找

插值查找是对二分查找的改进。它利用了列表中元素的分布情况,通过插值来估计目标项的可能位置,并从该位置开始进行查找。这种方法对于元素在列表中均匀分布的情况效果特别好。时间复杂度仍然是 O(log n)。

以下是一个使用插值查找来查找整数 x 是否出现在有序列表 a 中的示例代码:

int interpolation_search(int a[], int n, int x) {
    int left = 0, right = n - 1;
    while (left <= right && x >= a[left] && x <= a[right]) {
        int pos = left + (right - left) * (x - a[left]) / (a[right] - a[left]);
        if (a[pos] == x) {
            return pos;
        } else if (a[pos] < x) {
            left = pos + 1;
        } else {
            right = pos - 1;
        }
    }
    return -1;
}
二叉查找树

二叉查找树是一种字典树,可以用来实现有序列表。它的基本思想是:将列表中的元素插入到一个二叉树中,并保证它们有序。然后,通过比较目标项与当前节点的值,就可以逐步缩小查找范围。

这种方法的时间复杂度可以是 O(n),最差情况下会退化为一个链表,但通常情况下仍然是 O(log n)。

以下是一个使用二叉查找树来查找整数 x 是否出现在有序列表 a 中的示例代码:

typedef struct node {
    int data;
    struct node* left;
    struct node* right;
} Node;

Node* insert(Node* root, int data) {
    if (root == NULL) {
        root = (Node*)malloc(sizeof(Node));
        root->data = data;
        root->left = root->right = NULL;
    } else if (data < root->data) {
        root->left = insert(root->left, data);
    } else if (data > root->data) {
        root->right = insert(root->right, data);
    }
    return root;
}

int search(Node* root, int x) {
    if (root == NULL || root->data == x) {
        return root == NULL ? -1 : 0;
    } else if (x < root->data) {
        return search(root->left, x);
    } else {
        return search(root->right, x);
    }
}
参考资料