本章简述
本章的主题是编写正确的程序,以一个二分搜索算法引入。
关于二分搜索
二分搜索的关键思想是如果t在x[0..n-1]中,那么它就一定存在于x的某个特定范围之内。该程序最重要的部分是大括号内的循环不变式,也就是关于程序状态的断言。
代码的开发是自上而下进行的(从一般思想开始,将其完善为独立的代码行),该正确性分析则是自下而上进行的,从每个独立的代码行开始,检查它们是如何协同运作并解决问题的。
关于循环是程序中比较重要的部分,关于其正确性的讨论分为3个部分,每个部分都与循环不变式密切相关。
- 初始化,循环初始化执行的时候不变式为真
- 保持,如果在某次迭代开始的时候以及循环体执行的时候,不变式都为真,那么,循环体执行完毕的时候不变式依然为真
- 终止,循环能够终止并且可以得到期望的结果
原理
本章内容展示的程序验证的诸多优势:问题很重要;需要认真编写代码;程序的开发需要遵循验证思想;可以使用一般性的工具进行程序的正确性分析。
- 断言。输入、程序变量和输出之间的关系勾勒出了程序的“状态”,断言使得程序员可以准确的阐述这些关系。
- 顺序控制结构。控制程序的最简单的结构莫过于采用“执行这条语句然后执行下一条语句”的形式。
- 选择控制结构
- 迭代控制结构
- 函数
总结:本章介绍了编写正确的程序的一小部分技术,编写简单的代码是得到正确程序的关键。
习题分析总结
1 . 添加边界控制条件0 <= l <= n -1<= u
/************************************************************************/
/*
* 《编程珠玑》第四章 编写正确的程序
* 习题4.6
* 2.把t在数组中第一次出现的位置返回给p
*/
/************************************************************************/
#include <iostream>
#include <cstdlib>
using namespace std;
//采用递归的形式实现二分搜索
int binarySearch(int *arr, int left, int right, const int &elem)
{
if (left > right)
return -1;
int middle = (left + right) / 2;
if (arr[middle] == elem)
return middle;
else if (arr[middle] < elem)
{
left = middle + 1;
return binarySearch(arr, left, right, elem);
}
else{
right = middle - 1;
return binarySearch(arr, left, right, elem);
}
}
const int N = 12;
int main()
{
int arr[N] = { 1, 2, 3, 6, 6, 6, 6, 7, 8, 9, 10, 12 };
int t, pos;
cin >> t;
pos = binarySearch(arr, 0, N - 1, t);
if (pos == -1)
cout << "The value is not exist." << endl;
while (pos >= 0 && arr[pos] == t)
{
pos--;
}
cout << "The position of value " << t << " is " << pos+1 << endl;
system("pause");
return 0;
}
3 . 给出递归形式以及迭代形式的二分搜索算法实现。
/************************************************************************/
/*
* 《编程珠玑》第四章 编写正确的程序
* 习题4.6
* 3.对比分析递归实现的二分搜索和迭代实现的二分搜索。
*/
/************************************************************************/
#include <iostream>
#include <cstdlib>
using namespace std;
//采用递归的形式实现二分搜索
//int binarySearch(int *arr, int left, int right, const int &elem)
//{
// if (left > right)
// return -1;
// int middle = (left + right) / 2;
//
// if (arr[middle] == elem)
// return middle;
// else if (arr[middle] < elem)
// {
// left = middle + 1;
// return binarySearch(arr, left, right, elem);
// }
// else{
// right = middle - 1;
// return binarySearch(arr, left, right, elem);
// }
//}
//采用迭代的形式实现二分搜索
int binarySearch(int *arr, int left, int right, const int &elem)
{
if (left > right)
return -1;
while ( left < right)
{
int middle = (left + right) / 2;
if (arr[middle] == elem)
return middle;
else if (arr[middle] < elem)
{
left = middle + 1;
}
else{
right = middle - 1;
}
}
}
const int N = 12;
int main()
{
int arr[N] = { 1, 2, 3, 6, 6, 6, 6, 7, 8, 9, 10, 12 };
int t, pos;
cin >> t;
pos = binarySearch(arr, 0, N - 1, t);
if (pos == -1)
cout << "The vlue is not exist." << endl;
cout << "The position of value " << t << " is " << pos << endl;
system("pause");
return 0;
}
注释部分采用递归形式实现该算法,下面部分采用迭代形式实现该算法。
5 . 对于下面这个函数,在输入x为正整数时能够终止的。
while(x != 1) do
if even(x)
x = x/2
else
x = 3*x + 1
分析:even(x)函数返回>=x的最接近整数 , 输入x后,有限次执行if条件语句,直至 x=0 , 然后执行else语句使得x=1 , 下一次while判断,便退出循环。
9 . 此题给出几个简单的程序片段,都是可以正确退出循环的。