1. 程式人生 > >《C++語言程式設計基礎》學習之棧模板

《C++語言程式設計基礎》學習之棧模板

是隻能從一端訪問的線性群體,可以訪問的這一端稱棧頂,另一端稱棧底。棧是一種後進先出的資料結構。簡易計算器實現: 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;
}