2.复杂性、队列和堆栈

文章讨论了如何分析算法的资源需求,主要聚焦于运行时间和随机存取机(RAM)模型。插入排序作为例子,展示了如何分析其最佳和最坏情况下的运行时间复杂度。此外,还提到了二分查找的最坏情况运行时间,并介绍了基本数据结构,如堆栈和队列的实现及操作。
摘要由CSDN通过智能技术生成

Analyzing algorithms

分析算法

● We want to predict the resources that the algorithm requires.

● Usually, running time.

● In order to predict resource requirements, we need a computational model.

● 我们希望预测算法所需的资源。

● 通常是运行时间。

● 为了预测资源需求,我们需要一个计算模型。

The Random Access Machine (RAM) model

随机存取机(RAM)模型

● Instructions are executed one after another. No concurrent operations.

● It’s too tedious to define each of the instructions and their associated time costs.

● Instead, we recognize that we’ll use instructions commonly found in real computers:

● Arithmetic: add, subtract, multiply, divide, remainder, floor, ceiling). Also, shift left/shift

right (good for multiplying/dividing by ).

● Data movement: load, store, copy.

● Control: conditional/unconditional branch, subroutine call and return.

● Each of these instructions takes a constant amount of time.

● 指令一个接一个地执行。无并发操作。

● 定义每个指令及其相关的时间成本太乏味了。

● 相反,我们认识到我们将使用真实计算机中常见的指令:

● 算术:加法、减法、乘法、除法、余数、下限、上限)。此外,向左移动/移动

右(适用于乘以/除以)。

● 数据移动:加载、存储、复制。

● 控件:条件/无条件分支、子例程调用和返回。

● 这些指令中的每一条都需要一定的时间。

Numbers in the RAM model

RAM模型中的数字

The RAM model uses integer and floating-point types.

● We don’t worry about precision, although it is crucial in certain numerical applications.

● There is a limit on the word size: when working with inputs of size n, assume that

integers are represented by c lg n bits for some constant c >= 1. (lg n is a very

frequently used shorthand for .)

● Since c >= 1, we can hold the value of n, hence we can index the individual elements.

● Since c is a constant, the word size cannot grow arbitrarily.

RAM模型使用整数和浮点类型。

● 我们不担心精度,尽管它在某些数值计算中至关重要

● 单词大小有限制:当使用大小为n的输入时,假设对于某些常数c>=1,整数由c lg n位表示。 (lg n是一个非常常用的的简写)

● 由于c>=1,我们可以保持n的值,因此我们可以对各个元素进行索引。

● 由于c是常数,单词大小不能任意增长。

Analyze an algorithm’s running time

分析算法的运行时间

● The time taken by an algorithm depends on the input.

● Sorting 1000 numbers takes longer than sorting 3 numbers.

● A given sorting algorithm may even take differing amounts of time on two inputs of the same size.

● For example, insertion sort takes less time to sort n elements when they are already sorted than when they are in reverse sorted order.

● 算法所花费的时间取决于输入。

● 排序1000个数字比排序3个数字需要更长的时间。

● 给定的排序算法甚至可能在两个相同大小的输入上花费不同的时间。

● 例如,当n个元素已经排序时,插入排序所需的时间比按相反顺序排序时要少。

Input size

输入规模

Depends on the problem being studied.

● Usually, the number of items in the input. Like the size n of the array being sorted.

● But could be something else. If multiplying two integers, could be the total number of bits in the two integers.

● Could be described by more than one number. For example, graph algorithm running times are usually expressed in terms of the number of vertices and the number of edges in the input graph: <V,E>.

取决于正在研究的问题。

● 通常,输入的数目。类似于正在排序的数组的大小n。

● 但也可能是其他原因。如果乘以两个整数,则可以是两个整数中的总位数。

● 可以用多个数字来描述。例如,运行图形算法时间通常用输入图中的顶点数和边数表示:<V,E>。

Running time

运行时间

On a particular input, it is the number of primitive operations (steps) executed.

● Each line of pseudocode requires a constant amount of time.

● One line may take a different amount of time than another, but each execution of a given line i takes the same amount of time .

● This is assuming that the line consists only of primitive operations.

● If the line is a subroutine call, then the actual call takes constant time, but the execution of the subroutine being called might not.

● If the line specifies operations other than primitive ones, then it might take more than constant time. Example: “sort the points by x-coordinate.”

在特定输入上,它是执行的基本操作(步骤)的数量。

● 每行伪代码都需要一定的时间。

● 一行与另一行可能需要不同的时间,但每次执行给定的一行i需要相同的时间ci。

● 这是假设该行仅由基本操作组成。

● 如果该行是子例程调用,那么实际调用需要恒定的时间,但被调用的子例程的执行可能不会。

● 如果该行指定的操作不是基本操作,那么它可能需要的时间可能会超过常量。示例:“按x坐标排 序点。”

Insertion sort pseudocode

插入排序伪代码

Analysis of insertion sort

插入排序分析

● Assume that the i-th line takes time (constant). Since the third line is a comment, it takes no time.

● For j = 2, 3, … ,n, let be the number of times that the while loop test is executed for that value of j.

● Note that when a for or while loop exits in the usual way, the test is executed one time

more than the loop body.

● 假设第i行花费时间(常数)。由于第三行是注释,因此不需要花费时间。

● 对于j=2,3,…,n,设为对j值执行while循环测试的次数。

● 注意,当forwhile循环以通常的方式退出时,测试的执行次数比循环体多一次。

Analysis of insertion sort

插入排序分析

Precise running time

精确的运行时间

Best-case and worst-case running times

最佳情况和最坏情况运行时间

● 最佳情况:阵列已排序:

● 所有都是1。

● 可以将T(n)表示为常数a和b的an+b

● T(n)是n的线性函数。

● 最坏情况:数组的排序顺序相反

● 所有都是j。那么,从2到n的j的和是(n(n+1))/2-1(算术级数)。

● 对于常数a、b、c,T(n)=an2+bn+c。

● T(n)是n的二次函数。

Worst-case running time is the interesting one

最坏的运行时间是有趣的

We usually concentrate on finding the worst-case running time: the longest running time

for any input of size n, because:

● It time gives a guaranteed upper bound on the running time for any input.

● For some algorithms, the worst case occurs often. For example, when searching, the

worst case often occurs when the item being searched for is not present, and searches for absent items may be frequent.

● Average case is often about as bad as the worst case. For insertion sort, it is still quadratic (although half of running time).

我们通常专注于寻找最坏情况下的运行时间:任何大小为n的输入的最长运行时间,因为:

● 它的时间为任何输入的运行时间提供了一个保证的上限

● 对于某些算法,最坏的情况经常发生。例如,在搜索时,最坏的情况通常发生在所搜索的项目不存 在时,并且对缺席项目的搜索可能是频繁的。

● 一般情况通常与最坏情况一样糟糕。对于插入排序,它仍然是二次型(虽然是运行时间的一半)。

Order of growth

增长级

Another abstraction to ease analysis and focus on the important features.

Look only at the leading term of the formula for running time.

● Drop lower-order terms.

● Ignore the constant coefficient in the leading term.

For insertion sort, worst-case running time is +bn+c.

● After dropping low-order terms, we end up with .

● After ignoring constant coefficient, we end up with .

另一个简化分析并关注重要特性的抽象。

只看运行时间公式的前导项。

● 删除低阶术语。

● 忽略前导项中的常量系数。

对于插入排序,最坏的运行时间是+bn+c。

● 在删除低阶条件后,我们得到了一个

● 忽略常数系数后,我们得到

Big O notation

大O符号;表示法

We cannot say that the worst-case running time T(n) equals .

It grows like . But it doesn't equal .

We say that the running time is O() to capture the notion that the order of growth is .

We usually consider one algorithm to be more efficient than another if its

worst-case running time has a smaller order of growth.

我们不能说最坏的运行时间T(n)等于

它像那样增长。但它不等于

我们说运行时间是O(),以捕捉增长顺序是的概念。

我们通常认为一种算法比另一种算法更有效,如果最坏情况下,运行时间的增长顺序较小。

What we saw so far

到目前为止我们所看到的

● How to write algorithms in pseudocode.

● How to show correctness of algorithm.

● How to find time complexity of algorithm.

● That we are interested in the order of growth more than the precise complexity.

● 如何用伪代码编写算法。

● 如何显示算法的正确性。

● 如何找到算法的时间复杂度。

● 我们对增长的顺序比精确的复杂性更感兴趣。

Exercise: binary search in a sorted array

练习:排序数组中的二分查找

Referring back to the searching problem, observe that if the sequence A is sorted, we

can check the midpoint of the sequence against v and eliminate half of the sequence

from further consideration. The binary search algorithm repeats this procedure, halving

the size of the remaining portion of the sequence each time.

1. Write pseudocode, either iterative or recursive, for binary search.

2. Argue that the worst-case running time of binary search is O(lg n).

Help: assume that if T(n)=T(n/2)+O(1), then T(n)=O(lg n).

返回到搜索问题,观察到如果序列A被排序,我们可以根据v检查序列的中点并消除序列的一半

进一步考虑。二分查找算法重复此过程,减半每次序列的剩余部分的大小。

1.为二分查找编写伪代码(迭代或递归)。

2.论证了二分查找的最坏运行时间为O(lg n)。

帮助:假设如果T(n)=T(n/2)+O(1),则T(n)=O(lg n)。

Elementary data structures

基本的数据结构

● Let us examine the representation of dynamic sets by simple data structures that

use pointers.

● Our first examples of studying data structures with their operations will be stacks

and queues.

● 让我们通过简单的数据结构来研究使用指针的动态集的表示。

● 我们研究数据结构及其操作的第一个例子是堆栈队列

Stacks and queues

堆栈和队列

● Stacks and queues are dynamic sets equipped with a DELETE operation that

removes some element from the set. The element removed is prespecified (it is not

an argument of DELETE).

● In a stack, the element deleted from the set is the one most recently inserted: the

stack implements a last-in, first-out, or LIFO, policy.

● In a queue, the element deleted is always the one that has been in the set for the

longest time: the queue implements a first-in, first-out, or FIFO, policy.

● There are several efficient ways to implement stacks and queues on a computer, but

for now we see how to use a simple array to implement each.

● 堆栈和队列是配备了DELETE操作(从集合中删除某些元素)的动态集合

删除的元素是预先指定的(不是DELETE的参数)。

● 在堆栈中,从集合中删除的元素是最近插入的元素:堆栈实现后进先出(LIFO)策略。

● 在队列中,删除的元素始终是存在于集合中最长时间的:队列执行先进先出(FIFO)策略。

● 在计算机上实现堆栈和队列有几种有效的方法,但现在我们来看如何使用简单的数组来实现每一种。

Stacks

堆栈

● The INSERT operation on a stack is often called PUSH, and the DELETE operation, which does not take an element argument, is often called POP.

● These names are allusions to physical stacks, such as stacks of plates.

● The order in which plates are popped from the stack is the reverse of the order in which they were pushed onto the stack.

● 堆栈上的INSERT操作通常被称为PUSH,而不带元素参数的DELETE操作通常被称作POP。

● 这些名称暗指物理堆栈,例如一堆一堆的盘子。

● 板从堆叠中弹出的顺序与它们被推到堆叠上的顺序相反。

Array-based stack implementation

基于阵列的堆栈实现

● We can implement a stack of at most n elements with an array S[1..n]. The array has

an attribute S.top that indexes the most recently inserted element.

● The stack consists of elements S[1..S.top], where S[1] is the element at the bottom of

the stack and S[S.top] is the element at the top.

● Stack operations;

● STACK-EMPTY(S): test whether the stack S is empty

● PUSH(S,x)

● POP(S)

● 我们可以用数组S[1..n]实现最多n个元素的堆栈。该数组具有一个属性S.top,该属性为最近插入的元素编制索引。

● 堆栈由元素S[1.S.top]组成,其中S[1]是堆栈底部的元素,S[S.top]是顶部的元素。

● 堆栈操作;

● STACK-EMPTY(S):测试堆栈S是否为空

● 推动(S,x)

● 弹出(S)

Possible situations

可能的情况

Stack operations pseudocode and complexity

堆栈操作伪代码和复杂性

Queues

队列

● 队列上的INSERT操作为ENQUEUE。

● DELETE操作为DEQUEUE;

DEQUEUE不接受元素参数。

● 队列有头有尾。当一个元素进入队列时,它会在队列的尾部占据一席之地。

● 退出队列的元素始终是队列开头的元素。

Array-based queue implementation

基于阵列的队列实现

● 数组Q[1..n]可以表示最多n-1个元素的队列。

● Q、 tail指向将新元素插入队列的下一个位置。

● 最初,Q.head=Q.tail=1

● 当Q.head=Q.tail时,队列为空。

● 当Q.head=Q.tail+1或Q.head=1且Q.tail=n时,队列已满,如果我们尝试添加新元素时,队列将溢出。

Queue operations pseudocode and complexity

队列操作伪代码和复杂性

每个操作的时间复杂度为O(1)

(恒定时间)。

请注意,未进行下溢和上溢错误检查。

课后练习

Exercise: binary search in a sorted array

Referring back to the searching problem, observe that if the sequence A is sorted, we

can check the midpoint of the sequence against v and eliminate half of the sequence

from further consideration. The binary search algorithm repeats this procedure, halving

the size of the remaining portion of the sequence each time.

1. Write pseudocode, either iterative or recursive, for binary search.

2. Argue that the worst-case running time of binary search is O(lg n).

Help: assume that if T(n)=T(n/2)+O(1), then T(n)=O(lg n).

Exercises

1. Illustrate the result of each operation in the sequence PUSH(S,4), PUSH(S,1),

PUSH(S,3), POP(S), PUSH(S,8) and POP(S) on an initially empty stack S stored in

array S[1..6].

2. Explain how to implement two stacks in one array A[1..n] in such a way that neither

stack overflows unless the total number of elements in both stacks together is n. The

PUSH and POP operations should run in O(1) time.

3. Illustrate the result of each operation in the sequence ENQUEUE(Q,4),

ENQUEUE(Q,1), ENQUEUE(Q,3), DEQUEUE(Q), ENQUEUE(Q,8) and DEQUEUE(Q)

on an initially empty queue Q stored in array Q[1..6].

Exercises

4. Rewrite ENQUEUE and DEQUEUE to detect underflow and overflow of a queue.

5. Further rewrite ENQUEUE and DEQUEUE using the modulo (%) operator.

6. Whereas a stack allows insertion and deletion of elements at only one end, and a

queue allows insertion at one end and deletion at the other end, a deque (double-ended

queue) allows insertion and deletion at both ends. Write four O(1)-time procedures to

insert elements into and delete elements from both ends of a deque implemented by an

array.

7. Show how to implement a queue using two stacks. Analyze the running time of the

queue operations.

8. Show how to implement a stack using two queues. Analyze the running time of the

stack operations.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

带带萌新JAMMY BEAR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值