48
队队

队列. Queues 队列 队列 (Queues) 是生活中 “ 排队 ” 的抽象。队列 的特点是: – 一些元素的线形序列; – 新加入的元素排在队尾,出队的元素在对头

Embed Size (px)

Citation preview

队列

Queues 队列

队列 (Queues) 是生活中“排队”的抽象。队列的特点是:– 一些元素的线形序列; – 新加入的元素排在队尾,出队的元素在对头进行,即插入和删除只能在队的两段进行;

– 先来的先得到服务;故称为先进先出表 (FIFO, first in first out).

Definition of Queues

• 一个队列 (queue) 是同类型元素的线性表,其中插入在一端进行,删除在另一端进行。

• 删除进行的一端称为队头( the front , or the head). 最新加入的元素称为队尾( The rear or tail )。

• 例子 : 等待打印的任务构成一个队列;等待 CPU 服务的任务构成一个队列等。

Queue Operations

设 Queue_entry 表示队列元素的类型。

Constructor

Insertion (入队)

Queue Operations ( 2)Deletion出队

Get the front取队头元素

Queue Operations (3)

Check emptiness检查队是否空

The Queue Class

• The ADT Queue class:

class Queue {

public:

Queue();

bool empty() const;

Error_code append(const Queue_entry &x);

Error_code serve();

Error_code retrieve(Queue_entry &x)const;

};// the data part is left out

Extended Queue Operations

• If we want to add some operations on queues, for example, full, clear, serve_and_retrieve, one way is to extend the class Queue:

class Extended_queue:public Queue {

public:

bool full() const;

int size() const;

void clear();

Error_code serve_and_retrieve(Queue_entry &item);

};

队列

Implementations of Queues

如何表示队列元素呢?考虑连续队列,即用数组存储队列元素。

• The physical model

A linear array with

the front always in the first position

and all entries moved up the array whenever the front is removed.

Poor!

Linear Implementation (线性实现)• Two indices (下标) to keep track of both

the front and the rear of the queue

• To serve an entry, take the entry and increase the front by one

• To append an entry to the queue, increase the rear by one and put the entry in that position

• Problem: cannot reuse the discarded space

• When the queue is regularly emptied, this is good.

Circular Queue

Circular Arrays(循环数组)• 将数组设想为一个循环的,而非线性的;• 用两个下标 front 和 rear 记录队头和队尾位置;

• 添加元素时, rear 右移,将元素置于 rear位置。当 rear 等于 max 时 (last index), rear 置 0.

• 元素出队时,删除位于 front 位置的元素,然后 front 右移 . 当 front 等于 max 时 , 置 front 为 0 。

Boundary Conditions

rear front

frontrear

remove

rear front

frontrear

insert

empty after deletion

Full after addition

No difference

Boundary Conditions

• 问题:无法区分满队列与空队列。• 解决方法 :

1. 在数组中空一个位置;2. 使用一个布尔量表示队列是否满。当

rear 刚好到达 front 之前时,置 此标志为 true.

3. 使用一个计数器( counter )以记录队列中的元素个数。

Circular Implementation of Queues

template <class T> class Queue {

public:

Queue();

bool empty() const;

Error_code serve();

Error_code append(const T &item);

Error_code retrieve(T &item) const;

protected:

unsigned maxqueue;

int count;

int front,rear;

T entry[maxqueue];

};

Implementations of Queues

template <class T> Error_code Queue<T>::append(const T &item)

{ if(count >= maxqueue) return overflow; count++; rear = ((rear + 1) == maxqueue)?0:(rear +1); entry[rear] = item; return success;}

Implementations

template <class T> Queue <T>::Queue()

/*post: the queue is initialized to be empty*/

{

count =0;

rear = maxqueue -1;

// rear is just before the front position

//when it is empty

front = 0;

}

练习

试用一个 bool 变量区分队列满与空(不使用 count )实现循环队列

• 写出 队列的 class 定义;• 说明队列空和队列满的条件分别是什么;• 完成队列的实现。

队列

Demonstration and Testing

• To verify the methods, we write a demonstration program.

• The program interactively accepts commands and prints the results, a kind of black box testing.

• Testing is the process of executing a program with the intent of finding errors.

• Errors: valid input produces invalid output.

• Choosing those inputs which are likely to go wrong, especially the boundary cases.

Demonstration and Testing

1. Easy values. Test the program with data that are easy to check.

2. Typical, realistic values. Always try a program on data chosen to represent how the program will be used.

3. Extreme values. Many programs err at the limits of their range of applications.

4. Illegal values. A good program should output some sensible error message for invalid inputs.

Demonstration and Testing

• Alternatively, we can automate the testing: generate a sequence of operations and compare two queues (one is assumed to be the standard) to see if they have the same state after each operation (See lab1).

Testing and Debugging

• A classic book on testing, now also online:

The art of software testing, Glenford Myers

• Read Chapter 7 about debugging to reduce your effort on debugging.

Testing and Debugging

int main()

/*Post: Accept commands from user and execute them */

{

Extended_queue <int> test_queue;

introduction();// instructions for the user

while (do_command(get_command(), test_queue));

}

bool do_command(char c,

Extented_queue <int> &test_queue)

Pre: c is a valid command

Post: Perform the given command c on test_queue. Return false if c ==‘q’ (quit), otherwise, return true

void get_command()

Post: Get a valid command from the user and reurn it.

bool do_command(char c, Extended_queue<int> & test_queue)/*Post: perform the given commands. return true if c != 'q'. */{ bool continue_input = true; int x; switch(c) { case 'a'://append an item if (test_queue.full()) cout <<"full!"<<endl; else { cout << "input an integer:"<<endl; cin >> x; test_queue.append(x); }; break; case …. } return continue_input;}

char get_command(){

char command;

bool waiting = true;

cout <<"select a command and press enter:"<<endl;

while (waiting) {

cin >> command;

command = tolower(command);

if (command == 'a' || command == 'q' || command == 's' || command == 'r')

waiting = false;

else

cout << "enter a command" << endl;

}

return command;

}

队列

Software Lift Cycle

1. Analyze the problem precisely and completely. Be sure to specify all necessary user interface with care.

2. Build a prototype and experiment with it until all specifications can be finalized.

3. Design the algorithm, using the tools of data structures and of other algorithms whose function is already known.

4. Verify that the algorithm is correct, or make it so simple that its correctness is self-evident.

5. Analyze the algorithm to determine its requirements. Make sure that it meets the specifications.

6. Code the algorithm into the appropriate programming language.

7. Test and evaluate the program on carefully chosen test data.

8. Refine and repeat the foregoing steps as needed for additional functions until the software is complete and fully functional.

9. Optimize the code to improve performance, but only if necessary.

10. Maintain the program so that it will meet the changing needs of its users.

• Requirement analysis: what the software will do;

• Algorithm design and analysis: how the task is done and if the algorithm satisfies the requirements;

• Coding and testing: coding the algorithm and testing the program to see if it satisfies the requirements;

• Maintenance: maintain the program so that it will meet the changing needs of its users.

Application: Airport Simulation

1.同一个跑道用于起飞与降落;

2.每个时间单位可以有一架飞机起飞或者降落,但不允许同时降落与起飞;

3.每个时间单位到达的飞机数是随机的;

4.等待降落的飞机优先于等待起飞的飞机使用跑道;

5.等待的飞机分别置于降落队列和起飞队列;两个队列均有预设的长度。

Requirements(系统要求) : 在给定时间段的每个时间单位:

1.生成随机数目的到达飞机和起飞飞机;Generate random number of arriving planes and taking off planes.

2.处理到达的飞机: for each arriving plane, put the plane into the landing queue if the landing queue is not full, otherwise, refuse (direct it to another airport);

3.处理起飞飞机: put them into taking off queue;4. Taking care of the runway: if the landing queue

is not empty, let one land. Otherwise, if the taking off queue is not empty, let one take off. Otherwise, let the runway idle.

Objects: Plane(飞机) , Runway(跑道)

Data Structures:

landing queue: arriving planes(到达的飞机)

taking off queue: planes ready to take off(准备起飞的飞机)

Plane Specification

The Runway Specification

… // more for statistic reason

};

本章要点

• 掌握队列的 ADT 定义;• 掌握连续队列的实现:循环队列;循环队列实现中边界问题;

• 掌握队列的应用。• 理解黑盒软件测试原则。