1.1 《算法》第一章之导论和基本编程模型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lwz45698752/article/details/84799816

《算法》全书组织结构

  1. 基础:介绍实现,分析和比较算法的基本原则和方法,包括下面概述的内容
  2. 排序:数组排序,优先队列,选举及归并等
  3. 查找:庞大的数据集查找指定条目的算法
  4. 图:图的主要内容是对象和它们的连接(有权重和方向),解决最短路径等问题
  5. 字符串:研究对字符串操作的算法
  6. 背景:讨论其他领域前沿,如运筹学

概述

  • 算法:解决问题的方法

  • 数据结构:便于算法操作的组织数据的方法

  • 本章介绍学习前的准备:

  1. Java基础编程模型(用到的Java库,语法等)
  2. 介绍数据抽象并定义抽象数据类型以进行模块化编程,介绍实现抽象数据类型的过程,即定义其API,通过Java的类机制来使用
  3. 学习三种基础的抽象数据类型:背包,队列,栈,然后用数组等实现它们的API,作为算法实现的样板和起点
  4. 分析算法性能方法:基本做法:先对性能提出假设,建模,实验验证,必要时重复上述过程分析算法性能方法
  5. 最后一个连通性问题,活学活用,最终实现union-find抽象数据结构

算法

  • 编写程序:计算机语言实现一个已有方法(载体)
  • 是算法,而不是编程语言描述解决问题的方法,该方法要有限,确定,有效
  • 以求两非负整数的公约数的算法为例(书)
  • 便于算法实现----》数据结构组织数据
  • 编写复杂问题,要理解,定义和控制问题的复杂度及分解这些问题,然后选择合适算法
  • 选择算法-》分析算法性能(时间空间复杂度)

基础编程模型

  • 使用特定编程语言使得分离算法的思想和实现细节变得困难,所以只用大部分编程语言共有的语法
  • 实现算法所用到的语言特性,软件库和操作系统特性称为基础编程模型,可作为文档来查询
  • P9显示本书代码风格,力求与各种Java编程惯例和语言构造相一致

Java程序基本结构

  • 原始数据类型:精确地定义整数,浮点数等(不同取值范围),组合为类似数学公式定义的表达式
  • 语句:声明,赋值,条件,循环,调用和返回
  • 数组:相同数据类型
  • 静态方法:封装和重用代码,使coder能用独立模块编程
  • 字符串:一连串字符
  • 标准输入/输出
  • 数据抽象:定义非原始数据类型,数据抽象和封装(自定义类)

原始数据类型和表达式

  • 数据类型:一组数据及对其所能进行的操作的集合
  • Java控制变量(通过标识符来引用),而变量有类型和值
  • 初级运算(加减乘除)的关键是参与运算的数据类型和产生的数据类型应该一致

表达式

  • Java运算符优先级:见书
  • 浮点-》整型,会截断小数部分,而非四舍五入
  • int型用一个字长为32位的机器字即可表示(有的电脑有字长为64位的机器字,但int型还是32位)
  • Java作为强类型语言,会检查类型的一致性
  • 用模板来描述语句结构(如判断语句)

代码的简便写法

  • 声明与初始化一起
  • 隐式赋值:i++;i +=2;
  • 单语句省略花括号

静态方法

  • 静态方法又称为函数
  • 典型静态方法:判断素数,计算平方根等(见书)
  • 方法的返回值替代表达式中的方法调用
  • 返回语句结束函数并将控制权交给调用者

方法性质

  1. 方法参数按值传递:方法处理的是参数的值,而不是参数本身,该方式使得改变参数变量的值对调用者无影响(不要试图修改参数变量来改变参数)。值传递意味数组参数将会是原数组的别名(指向同一个内存空间):方法中使用数组参数变量能引用调用者的数组并改变其内容(不能改变原数组变量本身)
  2. 方法名可重载
  3. 方法只能返回一个值,但能包含多个返回语句
  4. void的静态方法会产生副作用(输入输出等)

递归(❤)

  • 递归总有一个简单情况,方法的第一条语句总是包含return的条件语句
  • 递归调用自己总是去尝试解决子问题,hence,递归收敛到最简单的情况
  • 递归调用的父问题与子问题不该有交集(如二分法的子问题操作的数组部分不同)

静态方法库

  • 定义Java类中的一组静态方法
  • 模块化即面向对象编程
  • Java开发模式是编写一个静态方法库(包含main方法)来完成某任务,实现模块(静态方法库)化编程
  • main方法的参数是输入的字符串组成的数组
  • main方法可编成测试用例,当用例复杂时,可独立成一模块

外部库

  1. 系统标准库(默认导入):java.lang.*
  2. 导入的系统库
  3. 第三方库
  4. 本地库

  • 第三方及自己模块化方法编写的方法库扩展了编程模型
  • 用例指的是调用其他库中方法的程序
  • 实现指的是实现某API的Java代码
  • Math库方法实例(见书P17)
  • 本书编写的库(见P18-19)

自己编写库

  1. 编写用例,在实现算法中将计算过程分解为可控的部分
  2. 明确库与其对应的API(API将实现与调用分离)
  3. 实现API及能独立测试的main函数

tips

  • 创建数组时指明数组大小是因为让编译器知道为数组预留的空间
  • 数组的方法,包括reverse和矩阵乘法(见书)

字符串

  1. 一连串字符(char型值)组成
  2. 字符串拼接
  3. 字符串类型转换(同基本数据类型)
  4. 自动转换:基本数据类型+字符串=字符串
  5. 命令行参数:main方法的参数是命令行输入的字符串组成的数组
  6. 以后学习string类在Java中的表示方法

输入输出

  • 本书提供一外部库用以建立Java程序与外界交流的简易模型
  • 经典模型中,Java程序可从命令行参数或从一个抽象字符流(即标准输入流)中获得输入,并将输出写入一个名为标准输出流的字符流中
  • 我们需要考虑Java程序和操作系统之间的接口-》简要地讨论OS和IDE所提供的相应机制:
    • 默认情况下,命令行参数,标准输入输出与应用程序绑定,而应用程序是由能接受命令输入的操作系统或开发环境所支持 。我们笼统地用终端来指这个应用程序提供的供输入和显示的窗口

命令和参数

  • 通过命令行向OS输入命令行参数(默认为字符串),OS将其传递给Java程序
  • OS常用命令(见书,javac/java/more)

标准输出(❤)


  • 格式化输出(printf),第一个参数为格式字符串,描述第二个参数如何在输出被转化为一个字符串(PS:该方法有多个参数)
    1. 格式字符串第一个字符是%,后面跟一个字符表示的转换代码(如d,f,s), 之间可插入整数表示转换后的字符串宽度),若宽度不够,则左边加空格,要想右边加空格,要使用负宽度,若转换后的字符串宽度要大于指定宽度,则宽度设置忽略
    2. 实例: “3.2f”:表示小数位保留2位(小数点后的2,若对于字符串,则表示截取的长度),宽度为3(更多见书P23)
    3. 转换代码表示的数据类型和对应参数数据类型匹配
    4. Sring的format方法参数同printf

标准输入(❤)

  • 从标准输入流中获取数据
  • by default,系统会将标准输出定位到虚拟终端
  • 输入的内容即为输入流
  • 输入时,多参数用空白字符分隔,空白字符包括空格,制表符,换行符等
  • 我们标准输入库中静态方法的API(P24)

重定向和管道(理解基本意思)

  • 标准输入和输出使得我们可利用命令行的扩展功能,只需要向命令中加入提示符(> 或<),可将输出或输入重定向为一文件
  • 标准输出流默认打印至虚拟终端,可重定向为一文件
  • 标准输入流默认从终端读取数据,可重定向为一文件
  • 一个程序的输出重定向另一个程序的输入称为管道(% java Random 1000 10 20 | java Average)
  • 上述解释:两个Java程序,第一个产生随机数,第二个求平均值,将Random的标准输出流和Average的标准输入流指定为同一个流
  • 上述方法突破能处理的输入输出流的长度限制(计算机即使没有空间存储10亿个数也行),一边输出,将输出流的末尾添加字符串,一边输入,从输入流的开头删除字符串
  • 见书P25图

本书提供的库

  1. 基于文件的输入输出库(In,Out):我们库提供了向文件写入或读取文件的数组的方法
  2. 标准绘图库(StdDraw):当前,输入输出抽象层的重点只是文本字符串,加入标准绘图库(标准绘图抽象层),产生图像输出的抽象层,该标准绘图库默认比例尺为段位正方形(所有坐标均在0和1之间),标准的实现将画布显示为一窗口,图形为黑色,背景为白色,各API使用见书P26-27

二分查找

  • 特点:高效,应用广泛,借此展示学习算法的过程
  • 程序见P28
  • 关注其功能(波浪线处):输入流(这里重定向为一文本文件)获取entry,过滤掉存在于白名单文件(另一个文本文件)的entry,并打印(输出)输入流中还剩下的entry

数据抽象

即面向对象编程,模块化编程,其好处在于

  1. 模块化编程复用代码
  2. 方便构造数据结构(如链式)
  3. 准确定义算法问题,如对于一些算法问题,解决方式都是定义数据结构并高效地实现它们的一组操作

答疑

  1. Java的字节码:Java程序的一种低级表示,可以运行于JVM,将程序抽象为字节码并保证其跨平台性
  2. Java允许整型溢出并返回错误的值,因为Java对于原始数据类型不自动检查溢出
  3. 使用内置常数:Double.POSITIVE_INFINITY和Double.NEGATIVE_INFINITY可将double变量初始化为无限大
  4. Java自动进行类型转换
  5. 若使用一变量前未初始化,且代码中存在使用该未初始化的变量的路径,Java抛出编译异常
  6. 1/0与1.0/0.0,前者产生运行时除以0的异常(终止程序,由于该值未定义),后者是无穷大
  7. 只有原始数据类型定义<和>运算符
  8. 表达式a/b的商会向0取整
  9. &,|,^表示整数的位逻辑操作,&&和||仅在独立的布尔表达式中有效
  10. 嵌套if语句中的else与最近的if相搭配
  11. for循环头部代码和主体代码在同一个代码段中,递增变量循环结束后便不可用,而等价的while则不然

猜你喜欢

转载自blog.csdn.net/lwz45698752/article/details/84799816