《编程珠玑》阅读小记(4) — 编写正确的程序

本章简述

本章的主题是编写正确的程序,以一个二分搜索算法引入。

关于二分搜索

二分搜索的关键思想是如果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 . 此题给出几个简单的程序片段,都是可以正确退出循环的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一部分 编 程 技 术 第1章 性能监视工具 3 1.1 计算素数 3 1.2 使用性能监视工具 7 1.3 一个专用的性能监视工具 8 1.4 开发性能监视工具 10 1.5 原理 11 1.6 习题 11 1.7 深入阅读 12 第2章 关联数组 13 2.1 Awk中的关联数组 13 2.2 有穷状态机模拟器 16 2.3 拓扑排序 17 2.4 原理 20 2.5 习题 21 2.6 深入阅读 22 第3章 程序员的忏悔 23 3.1 二分搜索 24 3.2 选择算法 26 3.3 子程序库 28 3.4 原理 30 3.5 习题 31 第4章 自描述数据 33 4.1 名字—值对 33 4.2 记录来历 36 4.3 排序实验 37 4.4 原理 39 4.5 习题 39 第二部分 实 用 技 巧 第5章 劈开戈尔迪之结 43 5.1 小测验 43 5.2 解答 44 5.3 提示 44 5.4 原理 47 5.5 习题 48 5.6 深入阅读 49 5.7 调试(边栏) 49 第6章 计算机科学箴言集 51 6.1 编码 52 6.2 用户界面 53 6.3 调试 53 6.4 性能 54 6.5 文档 56 6.6 软件管理 56 6.7 其他 58 6.8 原理 58 6.9 习题 58 6.10 深入阅读 60 第7章 粗略估算 61 7.1 头脑热身 61 7.2 性能的经验法则 62 7.3 Little定律 64 7.4 原理 65 7.5 习题 66 7.6 深入阅读 67 7.7 日常速算(边栏) 67 第8章 人员备忘录 69 8.1 备忘录 69 8.2 原理 71 8.3 深入阅读 71 第三部分 人性化I/O 第9章 小语言 75 9.1 Pic语言 76 9.2 视角 79 9.3 Pic预处理器 81 9.4 用来实现Pic的小语言 83 9.5 原理 87 9.6 习题 88 9.7 深入阅读 89 第10章 文档设计 91 10.1 表格 92 10.2 三条设计原则 94 10.3 插图 94 10.4 文本 96 10.5 合适的媒介 98 10.6 原理 100 10.7 习题 101 10.8 深入阅读 101 10.9 次要问题目录(边栏) 101 第11章 图形化输出 103 11.1 实例研究 103 11.2 显示结果取样 105 11.3 原理 107 11.4 习题 108 11.5 深入阅读 110 11.6 拿破仑远征莫斯科(边栏) 110 第12章 对调查的研究 113 12.1 有关民意调查的问题 113 12.2 语言 114 12.3 图片 117 12.4 原理 119 12.5 习题 120 第四部分 算 法 第13章 绝妙的取样 123 13.1 取样算法一瞥 123 13.2 Floyd算法 124 13.3 随机排列 125 13.4 原理 127 13.5 习题 127 13.6 深入阅读 128 第14章 编写数值计算程序 129 14.1 问题 129 14.2 牛顿迭代 130 14.3 良好的起点 132 14.4 代码 133 14.5 原理 135 14.6 习题 135 14.7 深入阅读 137 14.8 数值算法的力量(边栏) 137 第15章 选择 141 15.1 问题 141 15.2 程序 142 15.3 运行时间分析 145 15.4 原理 148 15.5 习题 149 15.6 深入阅读 151 附录A C和Awk语言 153 附录B 一个子程序库 157 部分习题答案 165 索引 181

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值