栈和队列
0x00 基本概念
栈(Stack)是一个抽象数据类型(ADT),对一个集合的元素定义了两个基本操作,入栈(push)以及出栈(pop),栈遵循后进先出原则(LIFO, last in, first out),就像手枪的弹夹一样,最后放入的那颗子弹往往最先打出去。
此处说这是一个ADT抽象数据类型是因为其既可以用链表实现也可以用数组实现,实现的方法不唯一,其并不是一个存储(物理)结构,而是一个抽象数据类型,对于抽象数据类型准确的定义是指一个数学模型以及定义在该模型上的一组操作。
队列(Queue)也是一种抽象数据类型,其同样定义了两个基本操作,入队(enqueue)以及出队(dequeue),其遵循先进先出原则(FIFO, first in, first out),就像我们去买火车票排的那个队列一样,遵循先来后到,先来的先买,买完后出队(从队头删除),后来的自动站在队尾(在队尾添加)。
对于队列还有一种一般化(generalized)的形式就是双端队列(double-ended queue, 一般简写为deque),双端队列两头都可以进行插入(入队)和删除(出队)操作。
栈和队列均 ...
数据结构概念小结
0x00 存储结构
数据元素之间的关系有两种不同的表示方法:顺序映象和非顺序映象,并由此得到两种不同的存储结构:顺序存储结构和链式存储结构。
顺序存储:在计算机从用一组地址连续的存储单元依次存储线性表的各个数据元素称为顺序存储。
可随机存取表中元素。
除末尾外,在其余位置插入和删除操作需要移动数据。
存储密度大。
**链接存储:**用一组离散的可以位于任意位置的存储单元来存储线性表的数据元素称为链接存储,比如单链表。
存储密度小,在填充相同大小内存空间的情况下,使用顺序表存储的元素要比使用链表存储的元素多,因为链式存储每一个结点都需要附加一个占用空间指针域。
逻辑上的相邻结点,物理上不必相邻。
插入和删除操作灵活,无需移动其中元素。
获取某个结点数据时比顺序存储慢。
索引存储:除存储结点信息之外,还建立附加的索引表来标识结点的地址,索引表往往由若干索引项组成。
使用索引来确定结点的存储位置,检索速度快,但需要占用多余的空间来存储索引表。
**散列存储:**即为hash存储,力图将数据元素的存储位置与关键码之间建立确定的对应关系,以用来加速查找过程的存储结构。
可以 ...
数学专业词汇
导数: derivatives
二阶导数: second derivative
N阶导数: Nth derivative
对某一特定的点求导数: derivative at a point
偏导数: partial derivative
隐函数求导: implicit derivative
二阶隐函数求导: second implicit derivative
曲线斜率: curved line slope
极值点: extreme point
极限: limits
(函数的)收敛(性): convergence
泰勒展开式: Taylor series
洛必达法则: L'Hôpital's rule
积分: integral
不定积分: indefinite integral
定积分: definite integral
反常积分: improper integral
积分的原函数: antiderivative (anti-反导数, O(∩_∩)O哈哈~)
二重积分: double integral
三重积分: triple integral
多重积分: multi ...
C++ 内存对齐总结
0x00 C++ 内存管理机制
0x00 内存布局
如图:
从低地址到高地址(从下往上)依次为:
Text Segment(代码段): 英文也可以写为code segment,包含了程序的可执行代码,通常此段是可共享的,以便同样的可执行代码只需要在内存中存储一遍,同时此段是只读的,以防止程序分配内存时将其覆写。
Initialized Data Segment(初始化数据段): 有时英文也简写为data segment,用来存放程序的全局变量以及静态变量, 此段可进一步被分为初始化只读区域(initialized read-only area)以及初始化可写区域(initialized read-write area),例如如下两个全局变量:
12const char * str = "Hello World"; // 将会存储在初始化只读区域char * str = "Hello World"; // 将会存储在初始化可写区域
Uninitialized Data Segment(未初始化数据段): 又称为bss段,此段数据将 ...
Statelessness
Statelessness
依据REST架构,服务端不应当存储任何客户端session以及其他客户端状态信息。这个限制就叫做无状态(Statelessness)。从客户端发送到服务端的每一个请求必需包含服务端理解请求所需的全部信息,并且不能使用任何存储在服务端的上下文。session状态必需全部存储于客户端。客户端负责存储和维护所有的应用程序状态信息。
这同样意味着客户端需要向服务端发送所有状态信息,不管服务端是不是都用得上。同时不应当在服务端和session之间存在任何关联。
无状态意味着每个HTTP请求都是完全独立的。当客户端发送一个HTTP请求时,它应当包括服务端处理请求所需的所有的信息。服务端绝不依赖于任何之前的请求所包含的信息。如果(之前的请求所包含的)信息足够重要的话,客户端应当将其打包至当前请求中再发送一遍。
为了确保客户端可以使用这些无状态的API,服务端返回数据时,应当告知客户端需要创建哪些状态。
为了保持无状态,不要在服务端存储任何客户端的认证和授权信息,要在客户端发送的API请求中附带这些授权凭证。每一个请求必需保持独立并不受当前客户端之前会话的影响。
App ...
REST API Versioning
REST API Versioning
版本控制可帮助您在识别所需更改时快速迭代。
随着你的知识面以及系统的提升,API的修改是不可避免的。当它打破了现有客户端的整合时,管理这种变化带来的影响可能是一个挑战。
When to Version
当发生重大更改之后,API需要提升版本号。重大更改一般是指以下情况
返回数据格式的变化
返回值数据类型的变化(比如从整数变为浮点数)
从当前API中移除任一部分
重大更改后应当修改API的主要版本号或者内容响应类型
非重大更改,例如增加一个新的终结点或者新的响应参数,不应当修改主要的版本号。然而,当进行更改以支持客户可能遇到的一些问题时,比如收到缓存后的数据或者其他的一些API问题,跟踪这些次要版本的API可能会有很大帮助。
How to Version
REST并没有提供任何特定的版本控制方法,但是通常情况下会从下面3个角度来进行版本控制:
URI Versioning
在URI中直接进行版本控制是目前最常用的方法,但是其违反了URI必需用来定义唯一资源的准则。当版本更新时,这同样会打破客户端的集成。
例如:
12http://api.e ...
REST API Security Essentials
REST API Security Essentials
安全永远不是事后才考虑的。它必须是任何开发项目以及REST API的组成部分。有多种方法来保卫RESTful API,例如basic auth, OAuth等等。但是要记住一件事就是RESTful API必需是无状态的,所以请求的认证和授权必须不能依赖cookie或者session。相反,每个API请求必须带有一些授权信息,服务端每次收到请求后都要去验证这些信息。
REST Security Design Principles
这篇论文“The Protection of Information in Computer Systems” by Jerome Saltzer and Michael Schroeder提出了8条用于保持计算机系统内信息安全的原则,如下:
**最小权限(Least Privilege):**一个实体应当仅有其操作所需的最小权限。只有当实体需要某个权限的时候才授权给它,当其不需要某个权限的时候要即时撤销权限
安全设置缺省值(Fail-Safe Defaults): 一个用户对系统内任意资源的默认访问 ...
Idempotent REST Apis
Idempotent REST APIs
在REST API上下文中,当发送的多个请求产生的效果和一个请求相同时,这个REST API就是幂等的(idempotent)。
当你设计一个REST API的时候,你必需意识到使用API的人是可能会犯错误的。他们写出来的客户端代码,可能会将一个请求发送多遍,这些重复的请求可能是在无意间发出来的(例如,客户端程序错误),当然有时也是故意发送的(例如,网络超时)。你应当设计一个具有容错性的API使得当重复请求发生时并不会使系统变得不稳定。
一个幂等的HTTP方法是那种当被请求多次时并不会产生不同结果的HTTP方法。这与这个方法到底被请求了多少遍没有关系。结果应该是相同的。简要来说,这意味着请求成功执行的结果与执行次数无关。举个例子,在数学里,把0加到任意一个数字的操作都是幂等的。
如果你遵循REST准则来设计API,你将有如下的几个幂等的REST API, GET, PUT, DELETE, HEAD, OPTIONS以及TRACE。只有POST API不是幂等的。
POST不是幂等的
GET, PUT, DELETE, HEAD, OPT ...
HATEOAS Driven REST Apis
HATEOAS Driven REST APIs
HATEOAS (Hypermedia as the Engine of Application State 使用超媒体作为应用状态引擎) 是REST应用程序架构的约束之一,用来保证RESTful体系结构与其他网络应用体系结构之间的独特性。这个术语“hypermedia”指的是任何包含一个超链接或者其他媒体形式(诸如图像、电影或者文本)的内容。
这个体系结构允许你在响应体中使用超链接,以便客户端可以通过超链接动态定向到所需要的资源。这在概念上等价于web用户通过点击web页面上的超链接来到达其想要的页面或寻求期望的信息。
例如,下面的是对请求HTTP GET http://api.domain.com/management/departments/10的一个JSON响应体:
12345678910111213{ "departmentId": 10, "departmentName": "Administration", "location ...
REST – Content Negotiation
REST – Content Negotiation
一般情况下,资源可以有多种表示,最主要的原因是因为它可能由不同的客户端请求不一样的表现层。客户端请求一个合适的资源表现层就被称为内容协商(content negotiation)。
HTTP规定了集中内容协商机制——当可以获取多种资源的表述层时,为给定的响应选择最佳的资源表述层的方法。
——RFC 2616
Server-driven Vs Agent-driven Content Negotiation
如果是由服务端通过算法来为一个响应选取最佳资源表现层的话,那么这就被称为服务端驱动内容协商。如果由客户端或代理人来进行选取,则被称为代理人驱动内容协商。
事实上,你不会找到很多服务端驱动内容协商的例子,因为如果使用这种方法的话,你需要对客户端期望的内容形式做太多的假设。有关客户端上下文以及客户端如何处理资源表现层是(服务端)几乎不可能确定的。这种实现方法除了会让服务端变得复杂以外,同样也是没必要的。
所以大多数的REST API实现基于客户端驱动的内容协商。客户端驱动的内容协商依赖于HTTP请求头的使用或者资源的URI。
...