01什么是阶梯访问表
02一般解决方案:顺序查找
double rangeLimit[] = { 50, 60, 70, 80, 90, 100.1 }; //注意哨兵是100.1
char grade[] = { 'F', 'E', 'D', 'C', 'B', 'A' };
int linearSearch(double score)
{
// 找首次大于score的位置
int gradeIndex = 0;
for (; rangeLimit[gradeIndex] <= score; ++gradeIndex);
return gradeIndex;
}
int main(void)
{
double score;
while (1)
{
std::cin >> score;
// 输入检查
if (score > 100 || score < 0)
{
std::cout << "请重新输入\n";
continue;
}
// 顺序查找
std::cout << grade[linearSearch(score)] << std::endl;
}
return 0;
}
03优化 :二分查找(“二分答案”)
# define SEGMENTATIONS 6
double rangeLimit[] = { 50, 60, 70, 80, 90, 100 }; //最后一个可以是100
char grade[] = { 'F', 'E', 'D', 'C', 'B', 'A' };
int binarySearch(double score)
{
// 找首次大于score的位置
int left = 0, right = SEGMENTATIONS-1;
int gradeIndex = right;
while (left <= right)
{
int mid = (left + right) / 2;
if (rangeLimit[mid] > score)
{
gradeIndex = mid;
right = mid - 1;
}
else left = mid + 1;
}
return gradeIndex;
}
int main(void)
{
double score;
while (1)
{
std::cin >> score;
// 输入检查
if (score > 100 || score < 0)
{
std::cout << "请重新输入\n";
continue;
}
// 二分查找
std::cout << grade[binarySearch(score)] << std::endl;
}
return 0;
}
04全部代码
# include <iostream>
# define SEGMENTATIONS 6
double rangeLimit[] = { 50, 60, 70, 80, 90, 100.1 };
char grade[] = { 'F', 'E', 'D', 'C', 'B', 'A' };
int linearSearch(double score)
{
// 找首次大于score的位置
int gradeIndex = 0;
for (; rangeLimit[gradeIndex] <= score; ++gradeIndex);
return gradeIndex;
}
int binarySearch(double score)
{
int left = 0, right = SEGMENTATIONS-1;
int gradeIndex = right;
while (left <= right)
{
int mid = (left + right) / 2;
if (rangeLimit[mid] > score)
{
gradeIndex = mid;
right = mid - 1;
}
else left = mid + 1;
}
return gradeIndex;
}
int main(void)
{
double score;
while (1)
{
std::cin >> score;
// 输入检查
if (score > 100 || score < 0)
{
std::cout << "请重新输入\n";
continue;
}
// 顺序查找
//std::cout << grade[linearSearch(score)] << std::endl;
// 二分查找
std::cout << grade[binarySearch(score)] << std::endl;
}
return 0;
}
05补充阅读(33.7节)
对于端点的判断(到底用小于号还是小于等于号),不要先编译从结果倒推,这是一种偷懒(拖延“整理思绪”这一任务)。正确的做法是在编译前就弄明白每一个符号的含义。