一.debug
我们在运行程序的过程中,会有运行结果出现错误的情况,这个时候就需要我们去解决这些问题,这些问题就是bug,而我们去解决这个问题就是debug。我们可以使用断点调试,一步步的看源代码执行过程来发现代码的错误。一般在使用软件编辑代码时,可用鼠标在行序号前面打断点,进行调试。这是我们要作为程序员必须掌握的技能。
二.数据结构
某种逻辑关系组织起来的一批数据,按一定的映像方式把它存放在计算机存储器中,并在这些数据上定义了一个运算的集合,就叫做数据结构。
数据结构一般包括以下三个方面内容:
(1)数据元素之间的逻辑关系,也称数据的逻辑结构。
(2)数据元素及其关系在计算机存储器内的表示,称为数据的存储结构。
(3)数据的运算,即对数据施加的操作。
以下是常用数据结构的插入、删除与搜索操作的时间复杂度:
数据结构 | 一般情况 | 最差情况 | ||||
插入 | 删除 | 搜索 | 插入 | 删除 | 搜索 | |
数组/栈/队列 | O(1) | O(1) | O(n) | O(1) | O(1) | O(n) |
链表 | O(1) | O(1) | O(n) | O(1) | O(1) | O(n) |
双向链表 | O(1) | O(1) | O(n) | O(1) | O(1) | O(n) |
散列表 | O(1) | O(1) | O(1) | O(1) | O(n) | O(n) |
二分搜索树 | O(logn) | O(logn) | O(logn) | O(n) | O(n) | O(n) |
以下是常用排序算法的时间复杂度:
算法(用于数组) | 最好情况 | 一般情况 | 最差情况 |
冒泡排序 | O(n) | O(n²) | O(n²) |
选择排序 | O(n²) | O(n²) | O(n²) |
插入排序 | O(n) | O(n²) | O(n²) |
归并排序 | O(nlog(n)) | O(nlog(n)) | O(nlog(n)) |
快速排序 | O(nlog(n)) | O(nlog(n)) | O(n²) |
三.线性表
线性表是线性结构中最常用而又最简单的一种数据结构,线性表是线性结构的抽象,线性结构的特点是一对一的线性关系。
线性表是具有相同类型数据的n(n>=0)个数据元素的有序数列。通常记为:
(a1,a2,…,ai,…,an)
其中,n为表长,n=0时为空表。在线性表中相邻元素之间存在顺序关系。线性表有两种存储方式,顺序存储与链式存储。
四.栈和队列
严格意义上来说,也属于线性表,因为存储逻辑关系也属于“一对一”,所以栈与队列,同样分为顺序存储与链式存储。
- 栈
使用栈存储数据,讲究“先进先出”,即最先进栈,最后出栈。栈是只能在表尾进行插入或删除操作的线性表,通常我们称表尾为栈顶,表头为栈底,表尾插入称为入栈,表尾删除称为出栈。
![](https://i-blog.csdnimg.cn/blog_migrate/8894be5e60fb71f8b45b7c42d4e98490.jpeg)
c++在STL里面为我们提供了栈,使用stack时需要引入头文件#include<stack>。
stack<int>s | 创建一个空栈s,数据类型为int |
push(x) | x入栈 |
pop( ) | 出栈 |
top() | 取栈顶(不出栈) |
empty() | 判断栈是否为空,若为空则返回true |
size() | 求栈大小,返回栈中的元素个数 |
数组模拟与STL容器
1.新建⼀个栈
int stk[N], top = -1;//top指向栈顶。基底是0则top=-1,是1则top=0
stack<int>stk;
2.插⼊数据
stk[++ top] = x;//将x插⼊栈
stk.push(x);//将x⼊栈
3.删除栈顶元素
top--;//删去栈顶
stk.top();//删栈顶
4.查询栈顶数据
stk[top];
stk.top();//取栈顶
5.如何清空⼀个栈
5.1 依次判断top是否存在,并删除top。O(n)
5.2 直接将top指针指向基地址。O(1)
6.数组模拟和STL容器的区别:
6.1 STL⾥⾯的stack没有清空函数,只能⼀个⼀个出栈or新建⼀个栈。
6.2 数组模拟的栈可以O(1)取出从栈顶往下数第k个元素(stk[top - k + 1),⽽STL实现的栈不可以。
例题
题目描述:
所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。
如:{3*(5-2)+7}3*(5-2)+7 对应的后缀表达式为3.5.2.-*7.+@。在该式中,@ 为表达式的结束符号。. 为操作数的结束符号。
#include<iostream>
#include<stack> //使用STL提供的栈需要的头文件
#include<cstdio>
#include<cstring>
using namespace std;
int sum,k;
string s;
stack <int> stk;// 创建栈
int main()
{
getline(cin,s);
for(int i=0;s[i]!='@';i++)
{
if(s[i]=='.')
{
sum=0,k=1;
for(int j=i-1;j>=0&&s[j]>='0'&&s[j]<='9';j--)
sum=sum+(s[j]-48)*k,k*=10;
stk.push(sum);
continue;
}//乘10的幂,将字符转换为十进制数,放入栈内。
if(s[i]>='0'&&s[i]<='9')
continue;
sum=stk.top();
stk.pop();
if(s[i]=='+') sum=stk.top()+sum;
if(s[i]=='-') sum=stk.top()-sum;
if(s[i]=='*') sum=stk.top()*sum;
if(s[i]=='/') sum=stk.top()/sum;
stk.pop();
stk.push(sum);//遇见运算符的时候,取栈顶元素进行计算;
}
cout<<stk.top();//输出结果
return 0;
}
- 队列
队列存储数据,保证“先进先出”,队列插入操作称为入队,队列删除操作称为出队,允许插入的一端称为队尾,允许删除的一端称为队头,不含任何数据元素的队列叫空队。
c++同样在STL里面为我们提供了队列,使用队列时需要引入头文件#include<queue>。
queue < int > q | 建立一个队列q,其内部元素类型是 int。 |
q.push(a) | 将元素 a 插入队列 q 的末尾。 |
q.pop() | 将 q 的队首元素删除.。 |
q.front() | 查询 q 的队首元素。 |
q.end() | 查询 q 的队尾元素。 |
q.size() | 查询 q 的元素个数。 |
q.empty() | 查询 q 是否为空。 |
我们经常使用的为顺序队列,链队列,循环队列与优先队列。
顺序队列的使用,会有如图的情况,
![](https://i-blog.csdnimg.cn/blog_migrate/923bccbbccba1878f1a777d54148ebcd.jpeg)
此时队列为空或者剩余存储单元,这种现象称为“假溢出”。循环队列解决了顺序队列的“假溢出”现象,但是新的问题出现,队满的条件不再是rear=MAXSIZE-1,而是front==rear和队空条件相同。
![](https://i-blog.csdnimg.cn/blog_migrate/d889d608b08e4cbaae36168311a864cf.gif)
解决方法:损失一个单元不用,即循环队列中元素个数是MAXSIZE-1时就认为队列满。
循环队列的存储空间是连续的,且预先分配的,若循环队列的出队与入队元素数量变化较大时,就难以准确估计,若预先分配的空间估计过大,会造成空间浪费,估计过小会导致溢出。此时就可以使用链队列来解决这个问题。
优先队列:
优先队列是一种特殊的队列,它不遵守先进先出的原则,每一个元素都有一个被称为权的数据,它是按照优先级出队列的。分为最大优先队列(是指最大的元素优先出队)和最小优先队列(是指最小的元素优先出队)。
例题
题目描述:
n 个人围成一圈,从第一个人开始报数,数到 mm 的人出列,再由下一个人重新从 11 开始报数,数到 mm 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
queue<int> sum;
int main(){
int n,m,s=1;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
sum.push(i);
}
while(!sum.empty()){
if(s==m){
cout<<sum.front()<<" ";
sum.pop();
s=1;
}
else if(s!=m){
s++;
sum.push(sum.front());
sum.pop();
}
}
return 0;
}
五.vector
在 C++ 的 STL 中,给我们提供了一个可变长度数组,可变长度数组的头文件是 #include< vector >
说明 | 功能 |
vector v(N,i) | 建立一个可变长度的 int 数组 v,且初始有 N 个为 i 的元素。N,i 可以省略。 |
v.push_back(a) | 将元素 a 插入 v 的末尾。 |
v.size() | 返回元素个数。 |
v.resize(n,m) | 重新调整数组大小为 n。如果 n 比原来大,则新增的部分都初始化为 m。 |
v[a] | 访问下标为 a 的元素。 |