数据结构、算法及线性表总结
一.思维导图
二.重要概念的笔记
1.算法
1.算法是对特定的问题求解步骤的一种描述。算法描述有自然语言、流程图、伪代码(重点掌握)。
2.通过时间复杂度和空间复杂度来评定一个算法的优劣。
3.特性:有穷性、确定性、可行性、输入、输出。
2.线性表
1.线性表分为顺序表和链表。
2.顺序存储结构的特点在逻辑上相邻(物理位置相邻),可实现随机存储(快速访问)。
3.链式存储数据元素存放在一组任意地址的储存节点,空间效率低,适合随机的插入和删除操作。
3.栈和队列
1.栈:后进先出(LIFO),入栈和出栈均在栈顶进行。
2.队列:先进先出 (FIFO),队头出队,队尾入队,可访问队头和队尾元素。
3.栈和队列操作都受限。
4.串
1.串是零或多个字符组成的有限序列,数据元素是一个字符。
2.串的模式匹配:BF算法(时间复杂度为 O(m*n)),KMP算法(时间复杂度为 O(m+n))。
5.数组与广义表
1.计算元素地址,例如A[m][n],求i行j列元素地址,每个元素占=所占空间为k。
行优先排列:首地址+(im+j)k
列优先排列:首地址+(in+j)k
三.疑难问题及解决方案
疑难问题 PTA题目:符号配对
思路:
括号匹配原则:将遇到的左括号进栈,当左边一堆左括号时,右边出现一个右括号,此右括号与最后一个左括号匹配。就将栈顶出栈,同理当右括号出现时,我们就要找他左边的括号,若匹配,则继续,若匹配失败,则错误。结束后判断栈是否为空,若栈空,则表明符号配对,若栈非空,则表明符号不配对。
做题目时会发现/与/该左右括号占两个字符位置,不好判断,经思考可解决,若遇到符号为/,该位置为合理位置且下一个符号为,则进栈两次,继续遍历。若遇到符号为,该位置为合理位置且下一个符号为/,则出栈两次,以此解决问题。
解决问题代码:
#include<iostream>
#include<stack>
#include<string>
#define N 200
#include"stdio.h"
#include"stdlib.h"
using namespace std;
int main()
{
char str[1000];
int i = 0, x = 0;
int flag = 0;
stack <char> p;
scanf("%c",&str[i]);
while (!(i >= 1 && str[i] == '\n' && str[i - 1] == '.'))
{
i++;
scanf("%c",&str[i]);
}
x = i - 1;
for (i = 0; i < x; i++)
{
switch (str[i]) {
case '{':case '(':case'[':
p.push(str[i]);
break;
case '/':
if (i + 1 < x && str[i + 1] == '*') {
p.push(str[i]);
p.push(str[i + 1]);
i++;
}
break;
case '*':
if (i + 1 < x && str[i + 1] == '/') {
if (!p.empty() && p.top() == '*') {
p.pop();
p.pop();
i++;
}
else flag = 1;
}
break;
case'}':
if (!p.empty() && p.top() == '{') {
p.pop();
}
else flag = 1;
break;
case']':
if (!p.empty() && p.top() == '[') {
p.pop();
}
else flag = 1;
break;
case')':
if (!p.empty() && p.top() == '(') {
p.pop();
}
else flag = 1;
break;
default:
break;
}
if (flag == 1) {
if (p.empty()) {
if (str[i] == '*') cout << "NO" << endl << "?-*/";
else cout << "NO" << endl << "?-" << str[i];
}
else {
if (p.top() == '*') cout << "NO" << endl << "/*-?";
else cout << "NO" << endl << p.top() << "-?";
}
break;
}
}
if (flag == 0) {
if(p.empty()) {
cout << "YES";
}
else cout << "NO" << endl << p.top() << "-?";
}
return 0;
}
···