注:以下内容均为个人复习使用,不保证所述内容绝对严谨;
注:考研知识点相对基础,因此这里只做知识点合集,不保证内容详细。
一、算法复杂度
时间复杂度,空间复杂度;
书写规则:
n趋近于无穷大
只关心最高阶
忽略系数(忽略常数)
(说白了这考题就是个极限等价问题,还只考你等价无穷大
(这里跟实操的时候考虑的还是不太一样,众所周知我的O(n)和dalao的O(n)是不一样的,100*n和n 天壤之别)
二、线性表
(易忘点:判满入栈/队,判空出栈/队)
定义
一、顺序表:(就是数组)
- 常考操作:插入、查找、删除、合并、就地转置
- 默认: 默认从下标0开始
二、链表:(就是类似于邻接表的东西)(后补:邻接表其实就是静态链表…)
- 分类: 单链表、双向链表、单循环链表、双向循环链表
- 常考操作: 插入、查找、删除、合并
- 静态链表:用结构体数组表示链表;特点:仍需提前预判空间规模,但删除插入操作O(1);eg.(邻接表)一类.
- “带头结点“ 与 ”不带头节点“ : 前者表示 头指针指向无值空间; 后者表示 头指针指向头元素(有值)。
三、常考点1:原地逆置
- 顺序表原地逆置: 头尾相应位置 swap( a ,b ) 。 额外空间O(1),时间复杂度O(n)。
- 链表原地逆置: 所有指针指向的地址不变,从头节点开始,逐一将 p->nex 修改为 已经逆置的链表部分的尾部。
四、常考点2:有序序列合并
- 顺序表合并时间复杂度过高,只需学会 双指针判断每个元素在总体序列的真正rank即可
- 链表序列合并:细节处理比较多。(也不知道考试要求的伪代码允许写多么伪,还是严格写比较好)
※※ 线性表热门考点 ※※
链表 原地逆置(手写代码)
有头节点时,head->nex为头元素;
无头节点时,head为头元素
//头指针为head,指向空
//原链表 head->a[1]->a[2]....->NULL
//目标形状: NULL <- a[1] <- a[2].... <-head
struct ss *pos,*later;
pos=head->nex;
head->nex=NULL;
while(pos!=NULL){
later= pos->nex;
pos->nex = head->nex;
head->nex = pos;
pos=later;
}
有序 链表合并(手写代码)
//双列合并
STU *p1=head1;
STU *p2=head2;
while(p1!=NULL){
STU *pre2=p2;
while( p2->nex!=NULL && p1->nex!=NULL &&
p2->nex->va < p1->nex->va ) p2=p2->nex;
STU *later2 = p2->nex;
p2->nex = p1->nex;
p1->nex = pre2;
p1=p2->nex; p2=later2;
}
cout<<"After congregation:"<<endl;
for(ss *i=head1->nex->nex;i;i=i->nex){//把两个头指针跳了
cout<<i->va<<" ";
} cout<<endl;
吐槽:上机写代码舒服多了,手写代码好像在create shit…
三、栈
定义
一、定义:尾进尾出 / top进 top出 的线性表
二、Tips:
坑点1:考研默认top指向空,内容位置在 [0,top-1]
坑点2:先判空再出栈,先判满再入栈
三、链栈: 指针+链表表示栈
四、 对顶栈
就是两个栈共用同一个连续空间,分别从该连续空间的两端向中间进行存储。
对顶栈栈满标志为 size_stack1+size_stack2==n;
链栈–定义
struct stack{//即单链表
stack *link;//指向该元素的下一个
int size value;//信息存储
};
struct stack * TOP;//top指针锁定栈地址
※※ 栈热门考点 ※※
非递归实现递归函数**
例子1:
//递归函数
int ack(int m,int n){
if(m==0) return n+1;
if(n==0) return ack(m-1,1);
return ack(m-1,ack(m,n-1));
}
//非递归--栈写法
int ack_in_stack(int m,int n){
int stack[N],top=0;
stack[top++]=m;stack[top++]=n;//top位指向空
whlie(top!=1){
m=stack[--top];
n=stack[--top];
if(m==0) stack[top++]=n+1;
else if(n==0) stack[top++]=m-1,stack[top++]=1;
else stack[top++]=m-1,stack[top++]=m,stack[top++]=n-1;
}
return stack[0];
}
较难:栈写 二叉树的前序遍历、后序遍历
后缀表达式
阅读方法(后缀转中缀):碰到一个运算符,取两个数字,运算结果放回数字序列
优先级问题:最先出现的运算符号最先计算
例: AB+CD - * EFG * - /
中缀: (A+B) * (C-D) / ( E - F * G )
前缀表达式
阅读方法(前缀转中缀):碰到一个数字取一个运算符跟在数字身后
优先级问题:最后出现的运算符号最先计算
例: + - * ^ ABCD / E / F + G H
中缀 A^B * C - D + E/F/ (G+H)
出栈顺序判断
手跑栈即可
括号匹配、进制转换
汉诺塔
书上栈和队列的部分还考了汉诺塔的手算题,
汉诺塔不是个dp吗2333,为社么放这里…
汉诺塔问题题解链接:博客链接
递归与非递归比较
递归比非递归:(效率低)速度慢、占用空间大;(用户友好)可读性更强,更容易证明,更清晰
四、 队列
一、定义:尾进头出 / rear进 front出 的线性表 二、 特殊存储结构:
链 队:纯链表
循环队列 :顺序表写队列时用,目的是为了防止队列的“假溢出”
双端队列 : 输入受限 两端出 一端入 输出受限 两端入 一端出
考点:出队顺序、和栈一起考
五、 矩阵压缩
特殊矩阵信息的压缩存储
考点主要在下标信息的相互转换、计算 且以下对于矩阵的名称 (定义同线性代数)暴力存储:O(n^2)
对称矩阵: 用线性数组存储一半矩阵的信息 O( (1+n)*n/2 )
三角矩阵: 线性数组存储一半矩阵的信息 O( (1+n)*n/2 )
稀疏矩阵: 这个意思基本跟邻接表存图差不多 O(M)
三对角矩阵 : 爪形行列式,首尾两行各有两个元素,其余行都是三个元素。
压缩存储方法:
三元组:
//只记录非0元素,未记录点默认为0.
int n,m,c;
struct ss{
int x,y,va;//行下标、列下标、值
}Poing[N];//point[i]表示原矩阵中第i个非零点 A[x][y[=va;
//另存三个数据: n,m,c,分别表示行数、列数、非零元素数
十字链表:
/*十字链表的结构类型定义如下:*/
typedef struct{
int x,y,va;//行下标、列下标、值
STU *right; //行方向后继
STU *down; //列方向后继
} STU;
typedef struct{
STU *X_head;//行链表头指针
STU *Y_head;//列链表头指针
int m,n,len; /*稀疏矩阵的行数、列数、非零元素的个数*/
} List;
二维矩阵连续空间存储地址的计算(注意下标起止点)
六、串
1. KMP算法
问题描述:判断短字符串是否为长字符串的子串
KMP算法的相关博客
时间复杂度:O(长串长度)
核心思想:nex数组表示公共前缀,回弹位置
2. 马拉车算法
问题描述:求最长回文子串
马拉车算法的相关博客
核心思想:回文串对称性质