[机试]第五章 数据结构一(向量、队列、栈)

part 1 向量

例题5.1 完数和盈数

KY272 完数与盈数

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <vector>

using namespace std;


int SumOfFactor(int num) {
    
    
	vector<int> factor;
	int result = 0;
	for (int i = 1; i < num; ++i) {
    
    
		if (num % i == 0) {
    
    
			factor.push_back(i);
		}
	}
	for (int i = 0; i < factor.size(); ++i) {
    
    
		result += factor[i];
	}
	return result;
}
int main() {
    
    
	vector<int> E, G;
	for (int i = 2; i <= 60; ++i) {
    
    
		if (i == SumOfFactor(i)) {
    
    
			E.push_back(i);
		}

		if (i < SumOfFactor(i)) {
    
    
			G.push_back(i);
		}
	}

	printf("E:");
	for (int i = 0; i < E.size(); ++i) {
    
    
		printf(" %d", E[i]);
	}
	printf(" G:");
	for (int i = 0; i < G.size(); ++i) {
    
    
		printf(" %d", G[i]);
	}

	return 0;
}
  • 数组的限制:必须在创建数组时确定其大小 -->向量:变长数组(向量的容量大于元素所需的实际容量,重新分配数组时,数组的大小呈双倍增长)
  • 向量基础
#include <vector>
vector<typename> name; // 定义
name.empty() name.size() //是否为空,返回元素个数
name.push_back() name.pop_pack() // 尾部添加、删除元素
name.insert(pos, ele) erase() clear() // 在某个位置插入,删除 清空向量
name.begin() end() // 首元素迭代器,尾元素后一个位置的迭代器

part 2 队列

例题5.2 约瑟夫问题NO.2

约瑟夫问题No.2_vjudge
约瑟夫问题No.2_poj-openjudge-百炼oj

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <queue>

using namespace std;

int main() {
    
    
	int n, p, m; // n个小孩 从p开始顺时针报数,到m出圈
	while (scanf("%d %d %d", &n, &p, &m) != EOF) {
    
    
		if (n == 0 && p == 0 && m == 0) {
    
    
			break;
		}
		queue<int> kids;
		for (int i = 1; i <= n; ++i) {
    
    
			kids.push(i);
		}
		for (int i = 0; i < p - 1; ++i) {
    
    
			kids.push(kids.front());
			kids.pop();
		}
		while (!kids.empty()) {
    
    
			for (int i = 0; i < m - 1; ++i) {
    
    
				kids.push(kids.front());
				kids.pop();
			}
			if (kids.size() == 1) {
    
    
				printf("%d\n", kids.front());
			}
			else {
    
    
				printf("%d,", kids.front());
			}
			kids.pop();
		}
	}
	return 0;
}
  • 队列:先进先出;队尾插入,队头删除
  • 队列基础
#include <queue>
queue<typename> name; //定义
name.empty() name.size() //是否为空,返回元素个数
name.push() name.pop() // 添加、删除元素
name.front() name.back() //获取队头,队尾元素
  • 利用queue队列模拟循环队列:将队首元素重新压入队尾,再弹出

说句题外话,会断点debug之后,感觉自己写的bug真的是脑瘫bug

例题5.3 猫狗收容所

在这里插入图片描述

INPUT:

6
1 1 
1 -1
2 0
1 2
2 -1 
2 1

OUTPUT:

1 -1 2
#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <queue>

using namespace std;

struct animal {
    
    
	int order;
	int type;
	animal(int t, int o): type(t), order(o){
    
    }
};


int main() {
    
    
	int n;
	int order = 0;
	queue<animal> cats;
	queue<animal> dogs;
	scanf("%d", & n);
	for (int i = 0; i < n; ++i) {
    
    
		int m, t;
		scanf("%d %d", &m, &t);
		if (m == 1) {
    
    
			if (t > 0) {
    
    
				dogs.push(animal(t, order++)); 
			}
			else {
    
    
				cats.push(animal(t, order++));
			}
		}
		else {
    
    
			if (t == 0 && !dogs.empty() && !cats.empty()) {
    
    
				if (dogs.front().order < cats.front().order) {
    
    
					printf("%d ", dogs.front().type);
					dogs.pop();
				}
				else {
    
    
					printf("%d ", cats.front().type);
					cats.pop();
				}
				
			}
			else if (t == 0 && dogs.empty() && !cats.empty()) {
    
    
				printf("%d ", cats.front().type);
				cats.pop();
			}
			else if (t == 0 && !dogs.empty() && cats.empty()) {
    
    
				printf("%d ", dogs.front().type);
				dogs.pop();
			}
			else if (t == 1 && !dogs.empty()) {
    
    
				printf("%d ", dogs.front().type);
				dogs.pop();
			}
			else if(t == -1 && !cats.empty()) {
    
    
				printf("%d ", cats.front().type);
				cats.pop();
			}
		}	
	}
	return 0;
}
  • 如果需要在队列里push一个自己创建的结构体,需要声明结构体的构造函数
  • 猫狗队列需要判断元素都不为零/有一方为0情况时的操作,考虑判断条件时应全面,尤其是特殊情况的考虑!(根据情况、题目条件权衡具体判断到多细致)

part 3 栈

例题5.4 Zero-complexity Transposition

KY109 Zero-complexity Transposition

#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <stack>
#include <string>

using namespace std;

int main() {
    
    
	int n;
	while (scanf("%d", &n) != EOF) {
    
    
		stack<string> list;
		for (int i = 0; i < n; ++i) {
    
    
			string str;
			cin >> str;
			list.push(str);
		}

		while (!list.empty()) {
    
    
			
			if (list.size() != 1) {
    
    
				cout << list.top() << " ";
				list.pop();
			}
			else {
    
    
				cout << list.top() << endl;
				list.pop();
			}
		}
	}
	return 0;
 }
  • 栈只能由栈顶进行操作,后进先出
  • 栈基础
#include <stack>
stack<typename> name; //栈的定义
name.empty() name.size() //是否为空,返回元素个数
name.push() name.pop() // 添加、删除元素
name.top() // 栈顶元素
  • 本题输入超出32位整型int示数(最大值 2的31次方 - 1 214748364)范围,也可以利用64位整型long long(最大值 2的64次方 - 1),其输入格式如下:(也可以直接用cin,系统之间没有差异)
    在这里插入图片描述

例题5.5 括号匹配问题

在这里插入图片描述

#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <string>
#include <stack>

using namespace std;

int main() {
    
    
	string str;
	while (cin >> str) {
    
    
		string ans(str.size(), ' ');
		stack<int> leftbrackets;
		for(int i = 0; i < str.size(); ++i){
    
    
			if (str[i] == '(') {
    
    
				leftbrackets.push(i);
			}
			else if (str[i] == ')') {
    
    
				if (!leftbrackets.empty()) {
    
    
					leftbrackets.pop(); // 匹配上了pop
				}
				ans[i] = '?';
			}
		}

		while (!leftbrackets.empty()) {
    
    
			ans[leftbrackets.top()] = '$';
			leftbrackets.pop();
		}
		cout << str << endl;
		cout << ans << endl;
	}
	return 0;
}
  • string初始化,string( size_type length, char ch ),length个ch初始化
  • #include<bits/stdc++.h>c++万能头文件,包含了目前c++所包含的所有头文件。有的oj支持有的不支持,vs是不支持万能头的,需要我们自己去手动添加。(tips:新手敲代码不要图方便使用万能头噢~)
  • 栈用来存左括号的下标,在最终判断左括号时就可以直接取下标输出了。

例题5.6 简单计算器

KY129 简单计算器

#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <cstdio>
#include <string>
#include <stack>
#include <cctype>

using namespace std;

double GetNumber(string str, int& index) {
    
    
	double num = 0;
	while (isdigit(str[index])) {
    
    
		num = num * 10 + str[index] - '0';
		index++;
	}
	return num;
}

int Priority(char c) {
    
    
	if (c == '#') {
    
    
		return 0;
	}
	else if (c == '$') {
    
    
		return 1;
	}
	else if (c == '+' || c == '-') {
    
    
		return 2;
	}
	else {
    
    
		return 3;
	}
}

double Calculate(double a, double b, char oper) {
    
    
	if (oper == '+') {
    
    
		return a + b;
	}
	else if (oper == '-') {
    
    
		return a - b;
	}
	else if (oper == '*') {
    
    
		return a * b;
	}
	else {
    
    
		return a / b;
	}
}


int main() {
    
    
	string str;
	while (getline(cin, str)) {
    
    
		if (str == "0") {
    
    
			break;
		}
		int index = 0;
		stack<char> oper;
		stack<double> data;
		str += '$';
		oper.push('#');

		while (index < str.size()) {
    
    
			if (str[index] == ' ') {
    
    
				index++;
			}
			else if (isdigit(str[index])) {
    
    
				data.push(GetNumber(str, index));
			}
			else {
    
    
				if (Priority(str[index]) > Priority(oper.top())) {
    
    
					oper.push(str[index]);
					index++;
				}
				else {
    
    
					double y = data.top();
					data.pop();
				    double x = data.top();
					data.pop();
					char op = oper.top();
					oper.pop();
					data.push(Calculate(x, y, op));
					
				}
			}
		}
		printf("%.2f\n", data.top());
	}
	return 0;
}


  • cctype头文件,该库的功能:负责字符分类功能如isalpha()字符转换功能如tolower(),isdigit() : Check if character is decimal digit
  • 当运算符栈顶元素的优先级大于当前位置运算符的优先级时,将栈顶运算符和最近进栈的两个数进行运算(注意运算符顺序,pop出来是逆序)
  • #表示最低优先级,最先入栈,为了将表达式的第一个符号压入;$倒数第二优先级,为了将式中的最低优先级符号进行运算。
  • 运算后不需要移动index!!这样才能持续的计算

习题5.1 堆栈的使用

KY180 堆栈的使用

#define _CRT_SECURE_NO_DEPRECATE
#include <cstdio>
#include <stack>

using namespace std;

int main() {
    
    
	int n;
	while (scanf("%d", &n) != EOF) {
    
    
		if (n == 0) {
    
    
			break;
		}
		char mode;
		stack<int> num;
		for (int i = 0; i < n; ++i) {
    
    
			scanf(" %c", &mode);
			if (mode == 'P') {
    
    
				int a;
				scanf(" %d", &a);
				num.push(a);
			}
			else if (mode == 'O') {
    
    
				if (!num.empty()) {
    
    
					num.pop();
				}
			}
			else if(mode == 'A'){
    
    
				if (!num.empty()) {
    
    
					printf("%d\n", num.top());
				}
				else {
    
    
					printf("E\n");
				}
			}
		}
		printf("\n");
	}
	return 0;
}
  • while大循环中读取整数n的scanf(%d)能识别\n但不能消除\n,后续如果接scanf(%c)读取的是\n,可以用getchar()来消除,也可以直接用cin
  • 对于scanf()而言,读取字符%c很特殊。
    1. %c前不加空格,scanf将读取标准输入流中的第一个字符
    2. %c前加空格,scanf将读取标准输入流中第一个非空白字符,可以实现屏蔽空白字符的作用

习题5.2 计算表达式

KY102 计算表达式

#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <cstdio>
#include <stack>
#include <string>
#include <cctype>

using namespace std;

double GetNumber(string str, int& index) {
    
    
	double num = 0; 
	while (isdigit(str[index])) {
    
    
		num = num * 10 + str[index] - '0';
		index++;
	}
	return num;
}

int Priority(char c) {
    
    
	if (c == '#') {
    
    
		return 0;
	}
	else if (c == '$') {
    
    
		return 1;
	}
	else if (c == '+' || c == '-') {
    
    
		return 2;
	}
	else {
    
    
		return 3;
	}
}

double Calculate(double x, double y, char oper) {
    
    
	if (oper == '+') {
    
    
		return x + y;
	}
	else if (oper == '-') {
    
    
		return x - y;
	}
	else if (oper == '*') {
    
    
		return x * y;
	}
	else {
    
    
		return x / y;
	}
}

int main() {
    
    
	string str;
	while (getline(cin, str)) {
    
    
		stack<double> data;
		stack<char> oper;
		int index = 0;
		str += '$';
		oper.push('#');
		while (index < str.size()) {
    
    
			if (isdigit(str[index])) {
    
    
				data.push(GetNumber(str, index));
			}
			else {
    
    
				if (Priority(str[index]) > Priority(oper.top())) {
    
    
					oper.push(str[index]);
					index++;
				}
				else {
    
    
					double y = data.top();
					data.pop();
					double x = data.top();
					data.pop();
					data.push(Calculate(x, y, oper.top()));
					oper.pop();
				}
			}
		}
		printf("%d\n", int(data.top()));
		data.pop();

	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44145782/article/details/119834820