數據結構
一、線性結構:單前驅,單後繼
只有前後關係,沒有上下級關係
1.1數組
1.2鏈表
1.3棧
存儲區藉助數組或鏈表
1.3.1數組實現
頭文件
#include "../../C/UTILITY.H"
#include "../../C/UTILITY.CPP"
typedef double Stack_entry; //類型複用,計算機才能識別Stack_entry,編譯爲double
#include "../STACK/STACK.H"
#include "../STACK/STACK.CPP"
#include "COMMANDS.CPP"
Stack的成員組成
const int maxstack = 10; // small value for testing
class Stack
{
public:
Stack();//構造stack,所以返回值肯定是stack,所以就不寫返回值
bool empty() const;//判空
Error_code pop();
Error_code top(Stack_entry &item) const;//返回棧頂最上元素//只有Error_code返回狀態碼正常,item纔是真正棧頂元素。
Error_code push(const Stack_entry &item); //
private:
int count;//棧裏的有效元素
Stack_entry entry[maxstack]; //存儲區
};
關於const:
const關鍵字放於函數後面,表示該函數是一個常成員函數,在該函數內不能修改該類的成員變量。
const關鍵字放於函數前面,表示該函數的返回值爲常量,不可以修改。
關於 Error_code
Error_code用於判斷是否成功存儲
P678頭文件utility.h
enum Error_code
{
success, fail, range_error, underflow, overflow, fatal, not_present, duplicate_error, entry_inserted, entry_found, internal_error
};
成員函數:
Stack::Stack()
Stack::Stack() /* Pre: None. Post: The stack is initialized to be empty. */
{
count = 0;
}
bool empty() const
bool Stack::empty() const /* Pre: None. Post: If the Stack is empty, true is returned. Otherwise false is returned. */
{
bool outcome = true;
if (count > 0) outcome = false;
return outcome;
}
這樣寫更簡潔明瞭
bool Stack::empty() const /* Pre: None. Post: If the Stack is empty, true is returned. Otherwise false is returned. */
{
return 0==count; //這樣寫不容易出錯,若寫成0=count編譯不能通過
}
Error_code Stack::push(const Stack_entry &item)
Error_code Stack::push(const Stack_entry &item) /* Pre: None. Post: If the Stack is not full, item is added to the top of the Stack. If the Stack is full, an Error_code of overflow is returned and the Stack is left unchanged. */
{
Error_code outcome = success;
if (count >= maxstack) //==本來就夠了,不可能大於,但不動腦筋就寫>=,寫代碼有多種選擇,邏輯正確就行
outcome = overflow; //上溢出
else
entry[count++] = item;
return outcome;
}
拿到數據item直接通過引用到數據區(用括號傳進來就直接傳給數據區<不能修改>),函數就是在判斷是否還有空間,而Error_code==success這個數據才真正成功存入存儲區。
Error_code Stack::pop()
Error_code Stack::pop() /* Pre: None. Post: If the Stack is not empty, the top of the Stack is removed. If the Stack is empty, an Error_code of underflow is returned. */
{
Error_code outcome = success;
if (count == 0)
outcome = underflow;
else
--count;
return outcome;
}
Error_code Stack::top(Stack_entry &item)
Error_code Stack::top(Stack_entry &item) const /* Pre: None. Post: If the Stack is not empty, the top of the Stack is returned in item. If the Stack is empty an Error_code of underflow is returned. */
{
Error_code outcome = success;
if (count == 0)
outcome = underflow;
else
item = entry[count - 1];//item被拷,因爲&item,引用,改變的就是存儲區的item
return outcome;
}
1.3.2數組棧的應用
1.3.2.1括號問題
// ==================== BRACKETS ================================ //MAIN.CPP
#include "../../C/UTILITY.H"
#include "../../C/UTILITY.CPP"
typedef char Stack_entry;
#include "../STACK/STACK.H"
#include "../STACK/STACK.CPP"
int main()
/* Post: The program has notified the user of any bracket mismatch in the standard input file. Uses: The class Stack. */
{
Stack openings;
char symbol;
bool is_matched = true;
cout << "Bracket checking program.\n"
<< "Enter a line of text to check." << endl;
while (is_matched && (symbol = cin.get()) != '\n')
{
if (symbol == '{' || symbol == '(' || symbol == '[') openings.push(symbol);
if (symbol == '}' || symbol == ')' || symbol == ']')
{
if (openings.empty())
{
cout << "Unmatched closing bracket " << symbol << " detected." << endl; is_matched = false;
}
else
{
char match; openings.top(match);
openings.pop();
is_matched = (symbol == '}' && match == '{')
|| (symbol == ')' && match == '(')
|| (symbol == ']' && match == '[');
if (!is_matched)
cout << "Bad match " << match << symbol << endl;
}
}
}
if (!openings.empty())
cout << "Unmatched opening bracket(s) detected." << endl;
}
1.3.2.2計算器
中綴表達式:a+b,(a+b)*(c+d)
後綴表達式:ab+,ab+cd+*
後綴表達式不需要括號 逆波瀾式reverse Polish calculator
二元運算符,連續彈出兩項,第一個彈出的是第二運算數,第二個彈出的是第一運算數
計算器對後綴表達式進行處理
int main() /* Post: The program has executed simple arithmetic commands entered by the user. Uses: The class Stack and the functions introduction, instructions, do_command, and get_command. */
{
Stack stored_numbers;
introduction();
instructions();
while (do_command(get_command(), stored_numbers));
}
//=================CALCULATOR=================== //COMMANDS.CPP-------------
void introduction()
{
cout << "Reverse Polish Calculator Program." <<"\n----------------------------------" << endl << endl;
}
void instructions()
{
cout << "User commands are entered to read in and operate on integers." << endl;
cout << "The valid commands are as follows:"
<< endl << "[Q]uit."
<< endl<< "[?] to enter an double number onto a stack."
<< endl << "[=] to print the top double number in the stack."
<< endl << "[+] [-] [*] [/] are arithmetic operations."
<< endl
<< "These operations apply to the top pair of stacked double numbers."<< endl;
}
char get_command() //取一個命令,一直輸入,直到輸入的是合法的
{
char command;
bool waiting = true;//上來就認爲不合適,要一直輸入,直到合法
cout << "Select command and press <Enter>:"; //選一個命令
while (waiting)
{
cin >> command;
command = tolower(command); //tolower把當前的字母變成小寫字母
if (command == '?' || command == '=' || command == '+' || command == '-' || command == '*' || command == '/' || command == 'q' ) //如果合法
waiting = false; //終止循環
else //如果使用者叛逆,沒有輸入7個合法命令
{
cout << "Please enter a valid command:" << endl
<< "[?]push to stack [=]print top" << endl
<< "[+] [-] [*] [/] are arithmetic operations" << endl << "[Q]uit." << endl;
}
}
return command;
}
bool do_command(char command, Stack &numbers) /* Pre: The first parameter specifies a valid calculator command. Post: The command specified by the first parameter has been applied to the Stack of numbers given by the second parameter. A result of true is returned unless command == 'q'. Uses: The class Stack. */
{
double p, q;
switch (command)
{
case '?':
cout << "Enter a real number: " << flush;
cin >> p;
if (numbers.push(p) == overflow)
cout << "Warning: Stack full, lost number" << endl;
break;
case '=':
if (numbers.top(p) == underflow)
cout << "Stack empty" << endl;
else
cout << p << endl;
break;
case '+':
if (numbers.top(p) == underflow)
cout << "Stack empty" << endl;
else { numbers.pop();
if (numbers.top(q) == underflow)
{
cout << "Stack has just one entry" <<endl;
numbers.push(p);
}
else
{
numbers.pop();
if (numbers.push(q + p) == overflow)
cout << "Warning: Stack full, lost result" << endl;
}
}
break; // Add options for further user commands. case '-': if (numbers.top(p) == underflow) cout << "Stack empty" << endl; else { numbers.pop(); if (numbers.top(q) == underflow) { cout << "Stack has just one entry" << endl; numbers.push(p); }else { numbers.pop(); if (numbers.push(q - p) == overflow) cout << "Warning: Stack full, lost result" << endl; } } break;
case '*':
if (numbers.top(p) == underflow) cout << "Stack empty" << endl; else { numbers.pop(); if (numbers.top(q) == underflow) { cout << "Stack has just one entry" << endl; numbers.push(p); }else { numbers.pop(); if (numbers.push(q * p) == overflow) cout << "Warning: Stack full, lost result" << endl; } } break;
case '/':
if (numbers.top(p) == underflow)
cout << "Stack empty" << endl;
else
if (p == 0.0)
{
cerr << "Division by 0 fails; no action done." << endl;
numbers.push(p);
// Restore stack to its prior state.
}
else
{
numbers.pop();
if (numbers.top(q) == underflow)
{
cout << "Stack has just one entry" << endl;
}
else
{
numbers.pop();
if (numbers.push(q / p) == overflow)
cout << "Warning: Stack full, lost result" << endl;
}
}
break;
case 'q':
cout << "Calculation finished.\n";
return false;
}
return true;
}
1.3.3鏈表棧
1.4隊列 queue
front指向哪,哪裏就是頭,而不是0號爲首。
retrieve(x);取隊首元素看一看,從x裏看
serve();出隊
append(‘a’);a入隊
取模運算,對10取餘數,可以形成閉環隊列
1.4.1實現
//QUEUE.H----------------------------------------------------------------------------------
const int maxqueue = 10; // small value for testing class Queue
{
public:
Queue();
bool empty() const; //判空,不會改變數據
Error_code serve();//出隊
Error_code append(const Queue_entry &item);// 入隊
Error_code retrieve(Queue_entry &item) const;//看首元素
protected:
int count; //計數器
int front, rear; //首未箭頭
Queue_entry entry[maxqueue];//Queue_entry類型的數據區
};
構造函數
// QUEUE.CPP -----------------------------------------------------------------------------------
Queue::Queue() /* Post: The Queue is initialized to be empty. */
{
count = 0; //初始化隊列裏無元素
rear = maxqueue - 1;//初始化尾下標是滿隊列-1
front = 0;
}
bool Queue::empty() const /* Post: Return true if the Queue is empty, otherwise return false. */
{
return count == 0;
}
入隊append
Error_code Queue::append(const Queue_entry &item) /* Post: item is added to the rear of the Queue. If the Queue is full return an Error_code of overflow and leave the Queue unchanged. */
{
if (count >= maxqueue) //如果隊列滿了,就不做了
return overflow;
count++;
rear = ((rear + 1) == maxqueue) ? 0 : (rear + 1);//如果下一個空溢出了,尾下標循環回0,否則正常下標向後推1(實現閉環隊列)
entry[rear] = item; //把item加入隊列
return success;
}
出隊serve
Error_code Queue::serve() /*Post: The front of the Queue is removed. If the Queue is empty return an Error_code of underflow. */
{
if (count <= 0)
return underflow;
count--;
front = ((front + 1) == maxqueue) ? 0 : (front + 1);
return success;
}
查看首元素
Error_code Queue::retrieve(Queue_entry &item) const /* Post: The front of the Queue retrieved to the output parameter item. If the Queue is empty return an Error_code of underflow. */
{
if (count <= 0) return underflow;
item = entry[front];
return success;
}
main
//MAIN.CPP----------------------------------------------------------------------------------
#include "../../C/UTILITY.H"
#include "../../C/UTILITY.CPP"
typedef char Queue_entry;
#include "QUEUE.H"
#include "QUEUE.CPP"
main()
{
cout << "Enter lines of text and the program duplicates them." << endl;
cout << "Use Ctrl-Z (EOF) to terminate the program." << endl;
while (cin.peek() != EOF)
{
Queue q;
char c;
while ((c = cin.get()) != '\n')
q.append(c);
while (!q.empty())
{
q.retrieve(c);
cout << c;
q.serve();
}
cout << endl;
}
}
擴充功能的隊列類
class Extended_queue: public Queue
{
public:
bool full() const;
int size() const;
void clear();
Error_code serve_and_retrieve(Queue_entry &item);
};
//EXTQUEUE.CPP----------------------------------------------------------------------------------
bool Extended_queue::full() const /* Post: Return true if the Extended_queue is full; return false otherwise. */
{
return count == maxqueue;
}
void Extended_queue::clear() /* Post: All entries in the Extended_queue have been deleted; the Extended_queue is empty. */
{
count = 0;
front = 0;
rear = maxqueue - 1;
}
int Extended_queue::size() const /* Post: Return the number of entries in the Extended_queue. */
{
return count;
}
Error_code Extended_queue::serve_and_retrieve(Queue_entry &item) /* Post: Return underflow if the Extended_queue is empty. Otherwise remove and copy the item at the front of the Extended_queue to item. */
{
if (count == 0)
return underflow;
else
{
count--;
item = entry[front];
front = ((front + 1) == maxqueue) ? 0 : (front + 1);
}
return success;
}
1.4.2 應用
1.4.2.1機場模擬程序
兩個類:飛機Plane 跑道Runway
兩個隊列:一個跑道有等待着陸的飛機隊列Landing queue和等待起飛的飛機隊列,但着陸的優先級高。
每個隊列元素爲Plane
enum Plane_status {null, arriving, departing};
class Plane
{
public:
Plane();
Plane(int flt, int time, Plane_status status); //p104
void refuse() const; void land(int time) const;
void fly(int time) const;
int started() const;
private:
int flt_num; //幾號飛機
int clock_start;
Plane_status state;
};
//PLANE.CPP-----------------------------------------------------------------------------------
Plane::Plane(int flt, int time, Plane_status status) /* Post: The Plane data members flt_num, clock_start, and state are set to the values of the parameters flt, time and status, respectively. */
{
flt_num = flt;
clock_start = time;
state = status;
cout << "Plane number " << flt << " ready to "; if (status == arriving) cout << "land." << endl; else cout << "take off." << endl;
}
Plane::Plane() /* Post: The Plane data members flt_num, clock_start, state are set to illegal default values. */
{
flt_num = -1;
clock_start = -1;
state = null;
}
void Plane::refuse() const /* Post: Processes a Plane wanting to use Runway, when the Queue is full. */
{
cout << "Plane number " << flt_num;
if (state == arriving)
cout << " directed to another airport" << endl;
else
cout << " told to try to takeoff again later" << endl;
}
void Plane::land(int time) const /* Post: Processes a Plane that is landing at the specified time. */
{
int wait = time - clock_start;
cout << time << ": Plane number " << flt_num << " landed after " << wait << " time unit" << ((wait == 1) ? "" : "s") << " in the landing queue." << endl;
}
void Plane::fly(int time) const /* Post: Process a Plane that is taking off at the specified time. */
{
int wait = time - clock_start;
cout << time << ": Plane number " << flt_num << " took off after " << wait << " time unit" << ((wait == 1) ? "" : "s") << " in the takeoff queue." << endl;
}
int Plane::started() const /* Post: Return the time that the Plane entered the airport system. */
{
return clock_start;
}
enum Runway_activity {idle, land, take_off};
class Runway
{
public:
Runway(int limit);
Error_code can_land(const Plane ¤t);
Error_code can_depart(const Plane ¤t);
Runway_activity activity(int time, Plane &moving); //
void shut_down(int time) const; //統計數據
private:
Extended_queue landing;
Extended_queue takeoff;
int queue_limit;
int num_land_requests; // number of planes asking to land
int num_takeoff_requests; // number of planes asking to take off
int num_landings; // number of planes that have landed
int num_takeoffs; // number of planes that have taken off
int num_land_accepted; // number of planes queued to land
int num_takeoff_accepted; // number of planes queued to take off
int num_land_refused; // number of landing planes refused
int num_takeoff_refused; // number of departing planes refused
int land_wait; // total time of planes waiting to land
int takeoff_wait; // total time of planes waiting to take off
int idle_time; // total time runway is idle };
//RUNWAY.CPP----------------------------------------------------------------------------------
Runway::Runway(int limit) /* Post: The Runway data members are initialized to record no prior Runway use and to record the limit on queue sizes. */
{
queue_limit = limit;
num_land_requests = num_takeoff_requests = 0;
num_landings = num_takeoffs = 0;
num_land_refused = num_takeoff_refused = 0;
num_land_accepted = num_takeoff_accepted = 0;
land_wait = takeoff_wait = idle_time = 0;
}
Error_code Runway::can_land(const Plane ¤t) /* Post: If possible, the Plane current is added to the landing Queue; otherwise, an Error_code of overflow is returned. The Runway statistics are updated. Uses: class Extended_queue. */
{
Error_code result;
if (landing.size() < queue_limit)
result = landing.append(current);
else result = fail;
num_land_requests++;
if (result != success)
num_land_refused++;
else
num_land_accepted++;
return result;
}
Error_code Runway::can_depart(const Plane ¤t) /* Post: If possible, the Plane current is added to the takeoff Queue; otherwise, an Error_code of overflow is returned. The Runway statistics are updated. Uses: class Extended_queue. */
{
Error_code result;
if (takeoff.size() < queue_limit)
result = takeoff.append(current);
else result = fail;
num_takeoff_requests++;
if (result != success)
num_takeoff_refused++;
else num_takeoff_accepted++;
return result;
}
Runway_activity Runway::activity(int time, Plane &moving) /* Post: If the landing Queue has entries, its front Plane is copied to the parameter moving and a result land is returned. Otherwise, if the takeoff Queue has entries, its front Plane is copied to the parameter moving and a result takeoff is returned. Otherwise, idle is returned. Runway statistics are updated. Uses: class Extended_queue. */
{
Runway_activity in_progress;
if (!landing.empty()) //有着陸的飛機
{
landing.retrieve(moving); //取走
land_wait += time - moving.started(); //等待的時間
num_landings++; //着陸了
in_progress = land; landing.serve(); //
}
else if (!takeoff.empty()) //沒有着陸的飛機,有起飛的飛機
{
takeoff.retrieve(moving); //起飛的取走
takeoff_wait += time - moving.started(); //起飛等待時間
num_takeoffs++;
in_progress = take_off;
takeoff.serve();
}
else //沒有着陸的飛機,沒有起飛的飛機
{
idle_time++;
in_progress = idle;
}
return in_progress;
}
void Runway::shut_down(int time) const /* Post: Runway usage statistics are summarized and printed. */
{
cout << "Simulation has concluded after " << time << " time units." << endl
<< "Total number of planes processed " << (num_land_requests + num_takeoff_requests) << endl
<< "Total number of planes asking to land " << num_land_requests << endl
<< "Total number of planes asking to take off " << num_takeoff_requests << endl
<< "Total number of planes accepted for landing " << num_land_accepted << endl
<< "Total number of planes accepted for takeoff " << num_takeoff_accepted << endl
<< "Total number of planes refused for landing " << num_land_refused << endl
<< "Total number of planes refused for takeoff " << num_takeoff_refused << endl
<< "Total number of planes that landed " << num_landings << endl
<< "Total number of planes that took off " << num_takeoffs << endl
<< "Total number of planes left in landing queue " << landing.size() << endl
<< "Total number of planes left in takeoff queue " << takeoff.size() << endl;
cout << "Percentage of time runway idle " << 100.0 * (( float ) idle_time) / (( float ) time) << "%" << endl;
cout << "Average wait in landing queue " << (( float ) land_wait) / (( float ) num_landings) << " time units";
cout << endl << "Average wait in takeoff queue " << (( float ) takeoff_wait) / (( float ) num_takeoffs) << " time units" << endl;
cout << "Average observed rate of planes wanting to land " << (( float ) num_land_requests) / (( float ) time) << " per time unit" << endl;
cout << "Average observed rate of planes wanting to take off " << (( float ) num_takeoff_requests) / (( float ) time) << " per time unit" << endl;
}
#include "../../C/UTILITY.H"
#include "../../C/UTILITY.CPP"
#include "PLANE.H"
#include "PLANE.CPP"
typedef Plane Queue_entry;
#include "../QUEUE/QUEUE.H"
#include "../QUEUE/QUEUE.CPP"
#include "../EXTQUEUE/EXTQUEUE.H"
#include "../EXTQUEUE/EXTQUEUE.CPP"
#include "RUNWAY.H"
#include "RUNWAY.CPP"
#include "../../B/RANDOM.H"
#include "../../B/RANDOM.CPP"
void initialize(int &end_time, int &queue_limit, double &arrival_rate, double &departure_rate) /* Pre: The user specifies the number of time units in the simulation, the maximal queue sizes permitted, and the expected arrival and departure rates for the airport. Post:Theprogramprintsinstructionsandinitializestheparametersend_time,queue_limit,arrival_rate, and departure_rate to the specified values. Uses: utility function user_says_yes */ { cerr << "This program simulates an airport with only one runway." << endl << "One plane can land or depart in each unit of time." << endl;
cerr << "Up to what number of planes can be waiting to land " << "or take off at any time? " << flush;
cin >> queue_limit; cerr << "How many units of time will the simulation run?" << flush;
cin >> end_time;
bool acceptable;
do
{
cerr << "Expected number of arrivals per unit time?" << flush; cin >> arrival_rate;
cerr << "Expected number of departures per unit time?" << flush; cin >> departure_rate;
if (arrival_rate < 0.0 || departure_rate < 0.0) cerr << "These rates must be nonnegative." << endl;
else acceptable = true;
if (acceptable && arrival_rate + departure_rate > 1.0) cerr << "Safety Warning: This airport will become saturated. " << endl; }
while (!acceptable);
} void run_idle(int time) /* Post: The specified time is printed with a message that the runway is idle. */ { cout << time << ": Runway is idle." << endl; } int main() // Airport simulation program /* Pre: The user must supply the number of time intervals the simulation is to run, the expected number ofplanesarriving,theexpectednumberofplanesdepartingpertimeinterval,andthemaximumallowed size for runway queues. Post: The program performs a random simulation of the airport, showing the status of the runway at each time interval, and prints out a summary of airport operation at the conclusion. Uses: Classes Runway, Plane, Random and functions run_idle, initialize. */ { int end_time; // time to run simulation int queue_limit; // size of Runway queues int flight_number = 0; double arrival_rate, departure_rate; initialize(end_time, queue_limit, arrival_rate, departure_rate); Random variable; Runway small_airport(queue_limit); for (int current_time = 0; current_time < end_time; current_time++) { // loop over time intervals int number_arrivals = variable.poisson(arrival_rate); // current arrival requests for (int i = 0; i < number_arrivals; i++) { Plane current_plane(flight_number++, current_time, arriving); if (small_airport.can_land(current_plane) != success) current_plane.refuse(); } int number_departures= variable.poisson(departure_rate); // current departure requests for (int j = 0; j < number_departures; j++) { Plane current_plane(flight_number++, current_time, departing); if (small_airport.can_depart(current_plane) != success) current_plane.refuse(); } Plane moving_plane; switch (small_airport.activity(current_time, moving_plane)) { // Let at most one Plane onto the Runway at current_time. case land: moving_plane.land(current_time); break; case take_off: moving_plane.fly(current_time); break; case idle: run_idle(current_time); } } small_airport.shut_down(end_time); }