《C++語言程式設計基礎》學習之棧模板
阿新 • • 發佈:2018-12-14
棧是隻能從一端訪問的線性群體,可以訪問的這一端稱棧頂,另一端稱棧底。棧是一種後進先出的資料結構。簡易計算器實現: Stack.h
#pragma once #ifndef STACK_H #define STACK_H #include<cassert> template<class T,int SIZE=50> class Stack { private: T list[SIZE]; int top; public: Stack(); void push(const T &item); T pop(); void clear(); const T &peek() const; bool isEmpty() const; bool isFull() const; }; //模板的實現 template<class T,int SIZE> Stack<T,SIZE>::Stack():top(-1){} template<class T, int SIZE> void Stack<T, SIZE>::push(const T&item) { assert(!isFull()); list[++top] = item; } template<class T, int SIZE> T Stack<T, SIZE>::pop() { assert(!isEmpty()); return list[top--]; } template<class T, int SIZE> const T&Stack<T, SIZE>::peek()const { assert(!isEmpty()); return list[top];//返回棧頂元素 } template<class T, int SIZE> bool Stack<T, SIZE>::isEmpty()const { return top == -1; } template<class T, int SIZE> bool Stack<T, SIZE>::isFull()const { return top == SIZE-1; } template<class T, int SIZE> void Stack<T, SIZE>::clear() { top = -1; } #endif // !STACK_H
Calculator.h
#pragma once #ifndef CALCULATOR_H #define CALCULATOR_H #include"Stack.h" class Calculator { //計算器類 private: Stack<double> s;//運算元棧 void enter(double num);//將運算元num壓入棧 //連續將兩個運算元彈出棧,放在opnd1和opnd2中 bool getTwoOperands(double &opnd1, double &opnd2); void compute(char op);//執行由操作符op指定的運算 public: void run();//執行計算器程式 void clear(); //清空運算元棧 }; #endif // !CALCULATOR_H
Calculator.cpp
#include "pch.h" #include"Calculator.h" #include<sstream> #include<cmath> #include <iostream> using namespace std; //工具函式,用於將字串轉換為實數 inline double stringToDouble(const string &str) { istringstream stream(str);//字串輸入流 double result; stream >> result; return result; } void Calculator::enter(double num) { s.push(num); } bool Calculator::getTwoOperands(double &opnd1, double &opnd2) { if (s.isEmpty()) { //檢查棧是否空 cerr << "Missing operand!" << endl; return false; } opnd1 = s.pop();//將右運算元彈出棧 if (s.isEmpty()) {//檢查棧是否空 cerr << "Missing operand!" << endl; return false; } opnd2 = s.pop();//將左運算元彈出棧 return true; } void Calculator::compute(char op) {//執行運算 double operand1, operand2; bool result = getTwoOperands(operand1, operand2); if (result){//如果成功,執行運算並將運算結果壓入棧 switch (op){ case '+':s.push(operand2 + operand1); break; case'-':s.push(operand2 - operand1); break; case'*':s.push(operand2 * operand1); break; case'/':if (operand1==0){//檢查除數是否為0 cerr << "Divided by 0!" << endl; s.clear();//除數為0時清空棧 } else { s.push(operand2 / operand1); break; } case '^':s.push(pow(operand2, operand1)); break; default: cerr << "Unrecognized operator!" << endl; break; } cout << "=" << s.peek() << "";//輸出本次運算結果 } else s.clear();//運算元不夠,清空棧 } void Calculator::run() {//讀入並處理字尾表示式 string str; while (cin >> str, str != "q") { switch (str[0]) { case'c':s.clear(); break; case'-'://遇'-'需判斷是減號還是負號 if (str.size() > 1) enter(stringToDouble(str)); else compute(str[0]); break; case'+'://遇到其它操作符時 case'*': case'/': case'^': compute(str[0]); break; default://若讀入的是運算元,轉換為整型後壓入棧 enter(stringToDouble(str)); break; } } } void Calculator::clear() {//清空運算元棧 s.clear(); } int main(){ Calculator c; c.run(); return 0; }
佇列的簡易實現:
#pragma once
#ifndef QUEUE_H
#define QUEUE_H
#include<cassert>
//類模板的定義
template<class T,int SIZE=50>
class Queue {
private:
int front, rear, count;//隊頭指標、隊尾指標、元素個數
T list[SIZE];//佇列元素陣列
public:
Queue();//建構函式,初始化隊頭指標、隊尾指標、元素個數
void insert(const T &item);//新元素入隊
T remove();//元素出隊
void clear();//清空佇列
const T &getFront() const;//訪問隊首元素
//測試佇列狀態
int getLength() const;//求佇列長度
bool isEmpty() const;//判斷佇列空否
bool isFull() const;//判斷佇列滿否
};
//建構函式,初始化隊頭指標、隊尾指標、元素個數
template<class T,int SIZE>
Queue<T,SIZE>::Queue():front(0),rear(0),count(0){}
template<class T, int SIZE>
void Queue<T,SIZE>::insert(const T&item){//向隊尾插入元素
assert(count != SIZE);
count++;//元素個數增1
list[rear] = item;//向隊尾插入元素
rear = (rear + 1) % SIZE;//隊尾指標增1,用取餘運算實現迴圈佇列
}
template<class T, int SIZE>
T Queue<T, SIZE>::remove() {
assert(count != 0);
int temp = front;//記錄下原先的隊首指標
count--;//元素個數自減
front = (front + 1) % SIZE;//隊首指標增1。取餘以實現迴圈佇列
return list[temp];//返回首元素值
}
template<class T, int SIZE>
const T&Queue<T, SIZE>::getFront()const {
return list[front];
}
template<class T, int SIZE>
int Queue<T, SIZE>::getLength()const {//返回佇列元素個數
return count;
}
template<class T, int SIZE>
bool Queue<T, SIZE>::isEmpty()const {//測試隊空否
return count == 0;
}
template<class T, int SIZE>
bool Queue<T, SIZE>::isFull() const {//測試隊滿否
return count == SIZE;
}
template<class T, int SIZE>
void Queue<T, SIZE>::clear() {//清空佇列
count = 0;
front = 0;
rear = 0;
}
#endif // !QUEUE_H
折半查詢(二分法查詢)演算法:對於已按關鍵字排序的序列,經過一次比較,可將序列分割成兩部分,然後只在有可能包含待查元素的一部分中繼續查詢,並根據試探結果繼續分割,逐步縮小查詢範圍,直至找到或找不到為止。
template<class T>
int binSearch(const T list[], int n, const T &key) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (key == list[mid])
return mid;
else if (key < list[mid])
high = mid - 1;
else
low = mid + 1;
}
return -1;
}