分块查找(也称为索引顺序查找)是一种在有序数组中进行查找的方法,它通过将数组分成若干块,并在每块中使用一个索引来加速查找过程。这种方法适用于数组太大而无法一次性加载到内存中,或者数组太大而不适合使用二分查找的情况。
### 分块查找的步骤:
1. **确定块大小**:首先,确定每个块包含多少元素。块的大小应该根据内存容量和查找效率来确定。
2. **创建索引**:为每个块创建一个索引,索引中包含每个块中的最大值和块的起始位置。
3. **确定目标块**:通过比较待查找的值与索引中的值,确定待查找的值可能位于哪个块中。
4. **在块内查找**:一旦确定了目标块,就在该块内进行顺序查找。
### 分块查找的优缺点:
**优点**:
- **减少比较次数**:对于大型数据集,分块查找可以显著减少比较次数,因为它首先在索引中进行查找,而不是直接在数据集中查找。
- **适用于外部存储**:当数据太大而无法完全加载到内存中时,分块查找可以有效地利用外部存储。
**缺点**:
- **额外的存储空间**:需要额外的空间来存储索引。
- **效率依赖于块大小**:块的大小对查找效率有很大影响。如果块太小,可能会有太多的块和索引需要维护;如果块太大,可能会减少查找效率。
- **块内顺序查找**:一旦确定了目标块,仍然需要在块内进行顺序查找,这可能会增加查找时间。
### 示例:
假设有一个有序数组,我们将其分成若干块,每块包含3个元素:
```
数组:[10, 12, 15, 20, 22, 25, 30, 31, 35, 40]
块1:[10, 12, 15] 索引:[15, 0]
块2:[20, 22, 25] 索引:[25, 3]
块3:[30, 31, 35] 索引:[35, 6]
块4:[40] 索引:[40, 9]
```
现在,如果我们想要查找值25,我们首先查看索引,发现25在第二块中(索引值为25,起始位置为3)。然后,我们直接跳到数组的第三个位置开始查找,这样就大大减少了查找所需的比较次数。
分块查找是一种有效的查找方法,特别是在处理大型数据集时,它可以显著提高查找效率。然而,它也需要仔细设计块的大小和索引结构,以确保最佳性能。
在C++中,`pair` 是一个非常有用的模板类,它包含两个元素,通常用于存储一对相关联的值。`pair` 定义在头文件 `<utility>` 中,并且是C++标准库的一部分。
### 基本用法
`pair` 可以存储任何类型的数据,只要这些类型是可以复制的。你可以使用 `pair` 来存储两个相关联的值,例如,一个键和它的值,或者两个相关的计算结果。
#include <iostream>
#include <utility> // 包含pair的定义
int main() {
std::pair<int, double> p = {1, 3.14};
std::cout << "First: " << p.first << ", Second: " << p.second << std::endl;
return 0;
}
在这个例子中,`p` 是一个 `pair`,包含一个整数和一个双精度浮点数。
### 成员变量
- `first`:用于访问 `pair` 中的第一个元素。
- `second`:用于访问 `pair` 中的第二个元素。
### 构造函数
`pair` 提供了多种构造函数,允许你以不同的方式初始化 `pair` 对象。例如,你可以在创建 `pair` 时直接指定两个元素:
std::pair<int, std::string> p = {10, "Hello"};
### 用途
`pair` 在标准库中广泛使用,特别是在容器如 `std::map` 和 `std::multimap` 中,这些容器的元素类型通常是 `std::pair<const Key, Value>`。
### 排序和比较
`pair` 支持默认的比较操作,首先比较第一个元素,如果第一个元素相等,则比较第二个元素。这使得 `pair` 可以直接用于需要排序的容器中,如 `std::vector` 或 `std::set`。
#include <algorithm>
#include <vector>
#include <utility>
int main() {
std::vector<std::pair<int, std::string>> vec = {{1, "one"}, {3, "three"}, {2, "two"}};
std::sort(vec.begin(), vec.end()); // 默认按第一个元素排序
for (const auto& p : vec) {
std::cout << p.first << ": " << p.second << std::endl;
}
return 0;
}
在这个例子中,`vec` 是一个包含 `pair` 的向量,`std::sort` 默认按照 `pair` 的第一个元素进行排序。
`pair` 是C++中一个非常灵活和强大的工具,用于处理成对的数据。
分块排序ai代码实现:
#include <iostream>
#include <vector>
using namespace std;
// 构建索引
vector<pair<int, int>> buildIndex(const vector<int>& data, int blockSize) {
int n = data.size();
vector<pair<int, int>> index;
for (int i = 0; i < n; i += blockSize) {
int maxVal = data[i];
for (int j = i + 1; j < i + blockSize && j < n; ++j) {
if (data[j] > maxVal) {
maxVal = data[j];
}
}
index.push_back({maxVal, i});
}
return index;
}
// 分块查找
int blockSearch(const vector<int>& data, const vector<pair<int, int>>& index, int target) {
int blockIndex = 0;
// 在索引中查找可能包含目标值的块
while (blockIndex < index.size() && target > index[blockIndex].first) {
++blockIndex;
}
// 在选定的块内进行顺序查找
int start = index[blockIndex].second;
for (int i = start; i < start + blockSize && i < data.size(); ++i) {
if (data[i] == target) {
return i; // 找到目标值,返回索引
}
}
return -1; // 未找到目标值
}
int main() {
vector<int> data = {10, 12, 15, 20, 22, 25, 30, 31, 35, 40};
int blockSize = 3;
int target = 25;
// 构建索引
vector<pair<int, int>> index = buildIndex(data, blockSize);
// 打印索引
cout << "Index:" << endl;
for (const auto& entry : index) {
cout << "(" << entry.first << ", " << entry.second << ")" << endl;
}
// 进行查找
int result = blockSearch(data, index, target);
if (result != -1) {
cout << "Element found at index: " << result << endl;
} else {
cout << "Element not found." << endl;
}
return 0;
}
手写代码实现:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <Windows.h> // 包含头文件
using namespace std;
#include <utility> // 包含pair的定义
int size = 10; //每块大小
int data_size = 100; //数组总大小
int max = 100; //随机生成数最大值
bool compare(int a, int b) { return a > b; }
//创建索引
vector<pair<int, int>> creatSY(const vector<int>& data, int size) {
vector<pair<int, int>> index;
int max_size = data.size() / size;
if (data.size() % size > 0) max_size++;
for (int i = 0; i < max_size; i++) {
pair<int, int> temp;
temp.first = i * size;
if (data.size() > (i+1) * size) {
temp.second = data[(i+1) * size -1 ];
}
else temp.second = data[data.size()-1];
index.push_back(temp);
}
return index;
}
int search(const vector<pair<int, int>>& p, const vector<int>& data,int target) {
for (int i = 0; i < p.size(); i++) {
if (p[i].second >= target) {
bool check = false;
for (int j = p[i].first; j < p[i].first+::size; j++) {
if (data[j] == target) {
check = true;
return j;
}
}
if (check == false) {
return -1;
}
}
}
return -1;
}
int main() {
srand(time(0));
int time = 0;
while (1) {
//分段查找----适用于数据量中等,同时可以减少比较次数
//确定块大小
//确定目标块
//在块内查找
vector<int>data(data_size);
for (int i = 0; i < data_size; i++) {
data[i] = rand() % ::max;
//data[i] = i; //为了确保能找到目标,不使用随机生成
}
//sort(data.begin(), data.end(),compare);
sort(data.begin(), data.end());
for (int i = 0; i < data.size(); i++)cout << data[i] << ' ';
cout << endl;
vector<pair<int, int>> p = creatSY(data, ::size);
for (const auto& entry : p) {
cout << "index : " << entry.first << " value : " << entry.second << endl;
}
int target = rand() % data_size;
cout << "target : " << target << endl;
//分组查找
int result = search(p, data, target);
if (result == -1) cout << "未找到目标" << endl;
else cout << "找到目标 index:" << result << endl;
Sleep(10);
time++;
if (time > 500) break;
}
}