一、冒泡排序函数模板
主程序测试整形数组、字符数组、字符串数组的排序(不使用STL)
//本程序实现从大到小排序
#include<iostream>
#include<string>
using namespace std;
template<typename T>
void BubbleSort(T a[], int n) {
for (int i = 1; i < n; i++) {
int temp = i;
T tmp;
for (int j = i - 1; j >= 0; j--) {
if (a[temp] > a[j]) {
tmp = a[temp];
a[temp] = a[j];
a[j] = tmp;
temp = j;
}
else break;
}
}
}
int n;
int t;
int main() {
cout << "请选择输入元素类型(1、整型,2、字符,3、字符串):";
cin >> t;
cout << "请输入元素个数:";
cin >> n;
int *a = new int[n];
char *b = new char[n];
string *c = new string[n];
cout << "请输入元素:";
switch (t) {
case 1:
for (int i = 0; i < n; i++) {
cin >> a[i];
}
BubbleSort(a, n);
for (int i = 0; i < n; i++) {
cout << a[i] << ' ';
}
break;
case 2:
for (int i = 0; i < n; i++) {
cin >> b[i];
}
BubbleSort(b, n);
for (int i = 0; i < n; i++) {
cout << b[i] << ' ';
}
break;
case 3:
for (int i = 0; i < n; i++) {
cin >> c[i];
}
BubbleSort(c, n);
for (int i = 0; i < n; i++) {
cout << c[i] << ' ';
}
break;
}
return 0;
}
二、类模板
Step1:设计一个通用的栈类(不使用STL),包含以下操作:
构造函数
析构函数
拷贝构造函数
判断是否为空
压栈操作
弹出操作
返回当前有几个元素
任意扩充栈大小的操作(resize)
重载赋值运算符
根据需要,设计其他操作
Step2:测试这个栈类模板
int 型栈
Double 栈
Char 栈
String 栈
Student 栈
说明:
栈是一种这样的数据结构:它像一个圆柱形的罐子,有底并且有一个开口。所以存放数据时,先放入的数据在下层,后放进的数据在上层;取出数据时,要按照顺序从上层开始取出。所以栈的操作特点是先进后出,后进先出。比如:把1、2、3放入栈,那么它们要按照3、2、1的顺序出栈;又比如:1、2、3保存在栈中,那么想取出2,操作步骤是:取出3、取出2、再放回3。在栈的操作中,“压栈”就是放入数据,“出栈”或“弹出”就是取出数据。
//Stack.h
#pragma once
#include"student.h"
#include<iostream>
using namespace std;
template <class E>
class Stack { //顺序栈类定义
private:
E* elements; //栈元素存放数组
int top; //栈顶指针
int maxSize; //栈最大容量
void overflowProcess(); //栈的溢出处理
public:
Stack(int sz = 50) {
maxSize = sz;
elements = new E[maxSize];
top = -1;
}; //构造函数
Stack(const Stack<E>& s); //拷贝构造函数
~Stack() { delete[]elements; } //析构函数
void Push(E x); //进栈
bool Pop(E& x); //出栈
bool getTop(E& x); //取栈顶内容
bool IsEmpty() const { return top == -1; } //判断是否为空
bool IsFull() const { return top == maxSize - 1; } //判断是否为满
int numOf() { return top+1; } //返回当前几个元素
void resize(int len);
Stack<E>& operator=(Stack<E>& s) {
top = s.top;
maxSize = s.maxSize;
elements = new E[maxSize];
for (int i = 0; i <= top; i++) {
elements[i] = s.elements[i];
}
return *this;
}
};
template <class E>
Stack<E>::Stack(const Stack<E>& s) {
maxSize = s.maxSize;
top = s.top;
elements = new E[maxSize];
for (int i = 0; i <= top; i++) elements[i] = s.elements[i];
}
template <class E>
void Stack<E>::overflowProcess() {
//私有函数:当栈满则执行扩充栈存储空间处理
E* newArray = new E[2 * maxSize]; //创建更大的存储数组
for (int i = 0; i <= top; i++)
newArray[i] = elements[i];
maxSize += maxSize;
delete[]elements;
elements = newArray; //改变elements指针
}
template <class E>
void Stack<E>::Push(E x) {
//若栈不满, 则将元素x插入该栈栈顶, 否则溢出处理
if (IsFull()) overflowProcess(); //栈满
elements[++top] = x; //栈顶指针先加1, 再进栈
}
template <class E>
bool Stack<E>::Pop(E& x) {
//函数退出栈顶元素并返回栈顶元素的值
if (IsEmpty()) return false;
x = elements[top--]; //栈顶指针退1
return true; //退栈成功
}
template <class E>
bool Stack<E>::getTop(E& x) {
//若栈不空则函数返回该栈栈顶元素的地址
if (IsEmpty()) return false;
x = elements[top];
return true;
}
template<class E>
void Stack<E>::resize(int len) {
if (len < top + 1) {
cout << "the length is not enough!" << endl;
return;
}
E* newArray = new E[len];
for (int i = 0; i <= top; i++) {
newArray[i] = elements[i];
}
maxSize = len;
elements = newArray;
}
//student.h
#pragma once
#include"Stack.h"
#include<string>
using namespace std;
class Student {
public:
Student(string s = "", double c = 0, double sc = 0) {
name = s;
credit = c;
score = sc;
}
void setStudentName(string s = "", double c = 0, double sc = 0);
void show();
bool check(string);
private:
string name;
double credit;
double score;
};
//student.cpp
#include"student.h"
#include<string>
#include<iostream>
#include<iomanip>
using namespace std;
void Student::setStudentName(string s, double c, double sc)
{
name = s;
credit = c;
score = sc;
}
void Student::show()
{
cout << "姓名:" << name << endl;
cout << "学分:" << credit << endl;
cout << "总成绩" << score << endl;
}
bool Student::check(string s)
{
return name == s;
}
//main.cpp
#include"Stack.h"
#include"student.h"
#include<iostream>
#include<string>
using namespace std;
string sss[4] = { "asdf", "asfd", "adfsdf", "ffff" };
int main() {
Stack<int> ints;
Stack<char> chars;
Stack<double> doubles;
Stack<string> strings;
Stack<class Student> students;
cout << "Stack<int> test:" << endl;
cout << "Is empty? " << ints.IsEmpty() << endl;
cout << "Push ";
for (int i = 1; i <= 10; i++) {
ints.Push(i); cout << i << " ";
}
cout << "\nnumber of elements: " << ints.numOf() << endl;
int x;
cout << "Is full? " << ints.IsFull() << endl;
cout << "resize 10" << endl;
ints.resize(10);
cout << "Is full? " << ints.IsFull() << endl;
cout << "copy to Stack<int> stack2, pop stack2" << endl;
Stack<int> ints1(ints);
cout << "Pop(getTop) ";
for (int i = 1; i <= 10; i++) {
ints1.getTop(x);
cout << x << " ";
ints1.Pop(x);
}
cout << "\nStack<int> stack3 = stack1" << endl;
Stack<int> ints2;
ints2 = ints;
cout << "pop: " << endl;
for (int i = 1; i <= 10; i++) {
ints2.Pop(x);
cout << x << " ";
}
cout << endl;
cout << "\nStack<double> test:" << endl;
cout << "Is empty? " << doubles.IsEmpty() << endl;
cout << "Push ";
for (double i = 0.01; i <= 10; i++) {
doubles.Push(i); cout << i << " ";
}
cout << "\nnumber of elements: " << doubles.numOf() << endl;
double y;
cout << "Is full? " << doubles.IsFull() << endl;
cout << "resize 10" << endl;
doubles.resize(10);
cout << "Is full? " << doubles.IsFull() << endl;
cout << "copy to Stack<double> stack2, pop stack2" << endl;
Stack<double> doubles1(doubles);
cout << "Pop(getTop) ";
for (int i = 1; i <= 10; i++) {
doubles1.getTop(y);
cout << y << " ";
doubles1.Pop(y);
}
cout << "\nStack<double> stack3 = stack1" << endl;
Stack<double> doubles2;
doubles2 = doubles;
cout << "pop: " << endl;
for (int i = 1; i <= 10; i++) {
doubles2.Pop(y);
cout << y << " ";
}
cout << endl;
cout << "\nStack<string> test:" << endl;
cout << "Is empty? " << strings.IsEmpty() << endl;
cout << "Push ";
for (int i = 0; i <= 3; i++) {
strings.Push(sss[i]); cout << sss[i] << " ";
}
cout << "\nnumber of elements: " << strings.numOf() << endl;
string z;
cout << "Is full? " << strings.IsFull() << endl;
cout << "resize 4" << endl;
strings.resize(4);
cout << "Is full? " << strings.IsFull() << endl;
cout << "copy to Stack<string> stack2, pop stack2" << endl;
Stack<string> strings1(strings);
cout << "Pop(getTop) ";
for (int i = 0; i <= 3; i++) {
strings1.getTop(z);
cout << z << " ";
strings1.Pop(z);
}
cout << "\nStack<string> stack3 = stack1" << endl;
Stack<string> strings2;
strings2 = strings;
cout << "pop: " << endl;
for (int i = 0; i <= 3; i++) {
strings2.Pop(z);
cout << z << " ";
}
cout << endl;
Student ss[4], aa;
for (int i = 0; i <= 3; i++) {
ss[i].setStudentName(sss[i], i + 10, i + 20);
cout << "push student" << i + 1 << ": ";
ss[i].show();
cout << endl;
students.Push(ss[i]);
}
for (int i = 0; i <= 3; i++) {
students.Pop(aa);
cout << "pop student:";
aa.show();
cout << endl;
}
return 0;
}
三、类模板
基于上面(题目二)设计的栈模板,设计实现一个简单的四则运算计算器,可以实现如下的操作:
例如: 1 + 2 * 3 – 4 / 2 # 答案:5
2.5 * 5 + 7 / 2 – 1 # 答案:15
3 + 2 * ( 12 - 9 ) - 8 / 4 #
( 3 + 2 ) * 4 - 18 / ( 1 + 2 * 4 ) + 2 #
3 + 4 #
//Stack.h
#pragma once
#include"Stack.h"
#include<iostream>
using namespace std;
template <class E>
class Stack { //顺序栈类定义
private:
E* elements; //栈元素存放数组
int top; //栈顶指针
int maxSize; //栈最大容量
void overflowProcess(); //栈的溢出处理
public:
Stack(int sz = 50) {
maxSize = sz;
elements = new E[maxSize];
top = -1;
}; //构造函数
Stack(const Stack<E>& s); //拷贝构造函数
~Stack() { delete[]elements; } //析构函数
void Push(E x); //进栈
bool Pop(E& x); //出栈
bool getTop(E& x); //取栈顶内容
bool IsEmpty() const { return top == -1; } //判断是否为空
bool IsFull() const { return top == maxSize - 1; } //判断是否为满
int numOf() { return top+1; } //返回当前几个元素
void resize(int len);
Stack<E>& operator=(Stack<E>& s) {
top = s.top;
maxSize = s.maxSize;
elements = new E[maxSize];
for (int i = 0; i <= top; i++) {
elements[i] = s.elements[i];
}
return *this;
}
};
template <class E>
Stack<E>::Stack(const Stack<E>& s) {
maxSize = s.maxSize;
top = s.top;
elements = new E[maxSize];
for (int i = 0; i <= top; i++) elements[i] = s.elements[i];
}
template <class E>
void Stack<E>::overflowProcess() {
//私有函数:当栈满则执行扩充栈存储空间处理
E* newArray = new E[2 * maxSize]; //创建更大的存储数组
for (int i = 0; i <= top; i++)
newArray[i] = elements[i];
maxSize += maxSize;
delete[]elements;
elements = newArray; //改变elements指针
}
template <class E>
void Stack<E>::Push(E x) {
//若栈不满, 则将元素x插入该栈栈顶, 否则溢出处理
if (IsFull()) overflowProcess(); //栈满
elements[++top] = x; //栈顶指针先加1, 再进栈
}
template <class E>
bool Stack<E>::Pop(E& x) {
//函数退出栈顶元素并返回栈顶元素的值
if (IsEmpty()) return false;
x = elements[top--]; //栈顶指针退1
return true; //退栈成功
}
template <class E>
bool Stack<E>::getTop(E& x) {
//若栈不空则函数返回该栈栈顶元素的地址
if (IsEmpty()) return false;
x = elements[top];
return true;
}
template<class E>
void Stack<E>::resize(int len) {
if (len < top + 1) {
cout << "the length is not enough!" << endl;
return;
}
E* newArray = new E[len];
for (int i = 0; i <= top; i++) {
newArray[i] = elements[i];
}
maxSize = len;
elements = newArray;
}
//main.cpp
#include"Stack.h"
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
bool analysis(string str) {
for (int i = 0; i < str.length(); i++) {
if (str[i] == '(' || str[i] == ')' || str[i] == '+' || str[i] == '-' || str[i] == '-' || str[i] == '*' || str[i] == '/') {
continue;
}
else if (str[i] >= '0' && str[i] <= '9') {
string tmp;
while (str[i] >= '0' && str[i] <= '9') {
tmp.push_back(str[i]);
i++;
}
if (str[i] == '.') {
i++;
if (str[i] >= '0' && str[i] <= '9') {
tmp.push_back('.');
while (str[i] >= '0' && str[i] <= '9')
{
tmp.push_back(str[i]);
i++;
}
}
else {
return false;
}
}
i--;
}
else return false;
}
return true;
}
string preop(string s) {
string n = "";
for (int i = 0; i < s.length(); i++) {
if (s[i] == ' ' || s[i] == '#') continue;
n += s[i];
}
return n;
}
string format(string str) { //部分负数补0
for (int i = 0; i < str.length(); i++) {
if (str[i] == '-') {
if (i == 0) str.insert(0, 1, '0');
else if (str[i - 1] == '(') {
str.insert(i, 1, '0');
}
}
}
return str;
}
double readD(string str, int& m)
{
int zh = 0;//整数部分
int w = 1;//符号
bool flag = false;//小数点
double xi = 0.0;//小数部分
double x = 1.0;//位
int i = 1;
char ch = str[0];//开读
while (ch >= '0' && ch <= '9')//整数部分
{
zh = zh * 10 + ch - '0';
ch = str[i++];
m++;
}
while (ch < '0' || ch > '9')//找小数点
{
if (ch == '.') { flag = true; m++; }
if (i >= str.length()) return zh;
ch = str[i++];
}
if (!flag) return zh;//没有返回整数
while (ch >= '0' && ch <= '9')//小数部分
{
x *= 10;
xi = xi + (ch - '0') / x;
ch = str[i++];
m++;
}
if (w == 1) return zh + xi;
else return zh - xi;
}
int priorisp(char x) {
if (x == '#') return 0;
if (x == '(') return 1;
if (x == '^') return 7;
if (x == '*' || x == '/') return 5;
if (x == '+' || x == '-') return 3;
if (x == ')') return 8;
printf("OPTR error\n");
return 0;
}
int prioricp(char x) {
if (x == '#') return 0;
if (x == '(') return 8;
if (x == '^') return 6;
if (x == '*' || x == '/') return 4;
if (x == '+' || x == '-') return 2;
if (x == ')') return 1;
printf("OPTR error\n");
return 0;
}
int main() {
string s;
getline(cin, s);
s = preop(s);
cout << s << '=';
Stack<double> nums;
Stack<char> ops;
ops.Push('#');
if (!analysis(s)) {
cout << "error!(points, spaces...(初步判断不合法))";
return 0;
}
s = format(s) + '#';
int idx = 0;
while (idx < s.length()) {
if (s[idx] >= '0' && s[idx] <= '9') {
double n;
int m = 0;
n = readD(s.substr(idx, s.length()), m);
nums.Push(n);
idx += m;
if (idx >= s.length()) break;
}
else if (s[idx] == '+' || s[idx] == '-' || s[idx] == '*' || s[idx] == '/' || s[idx] == '(' || s[idx] == ')' || s[idx] == '#')
{
char option = (char)s[idx];
char oped, res;
ops.getTop(oped);
if (prioricp(option) > priorisp(oped)) {
ops.Push(option);
idx++;
}
else if (prioricp(option) < priorisp(oped)) {
char a;
if (ops.IsEmpty()) {
cout << "Error!!!(缺少操作符)" << endl;
return 0;
}
ops.Pop(a);
double b;
if (nums.IsEmpty()) {
cout << "ERror!!(缺少操作数)" << endl;
return 0;
}
nums.Pop(b);
double c;
if (nums.IsEmpty()) {
cout << "ERRor!!!(缺少操作数)" << endl;
return 0;
}
nums.Pop(c);
if (a == '+') nums.Push(c + b);
else if (a == '-') nums.Push(c - b);
else if (a == '*') nums.Push(c * b);
else if (a == '/') nums.Push(c / b);
}
else {
ops.Pop(res);
idx++;
}
}
else
{
idx++;
continue;
}
}
if (nums.IsEmpty()) {
cout << "ERROR!!!(操作数栈为空)" << endl;
return 0;
}
double ans;
nums.Pop(ans);
if (nums.IsEmpty()) {
cout << ans << endl;
}
else cout << "ERROR!!!(操作数栈剩余两个数及以上)" << endl;
return 0;
}