目录
一、绪论
考点主要集中于T(n)和S(n)的计算
1.数据结构
2.算法
(1)T(n)
描述算法规模的大小
O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)<O(2^n)<(n!)<(n^n)
(2)S(n)
描述算法所需辅助空间大小
(3)主要求解步骤
step1:找主要的代码
step2:分析执行次数
(4)eg
1)while循环
int fun(int n){
int x = 1;
while(x < n){
x*=2;
}
}
step1:主要代码为while循环
step2:设执行次数为k,执行k次后:x * 2^k > n时截至
-> k = log2n +1 -> O(logn)
2)递归
int fun(int n){
if(n<=1) return 1;
return n * fun(n-1);
}
step1:主要代码为return n * fun(n-1) 递归
step2:设执行次数为k,执行k次后 n - k <=1
k = n -> O(n)
3)规模理解
int fun(int n){
int sum = 0;
for (int i = 1; i < n; i*=2) {
for (int j = 0; j < i; j++) {
sum++;
}
}
}
step1:主要代码为2层for循环
step2:设执行k次
分析:sum是结果,不控制for循环结束;i、j控制,下面i为多少时,j执行多少次
i 1 2 4 8 …… 2^(k-1)
j 1 2 4 8 …… 2^(k-1)
so all_j = 1+2+4+……+2^(k-1) = 2^k -1 < n
根据T(n)定义,此时2^k-1为问题规模,而不是k,因为k为次数,但是all_k为整体的问题规模
so -> O(n)
二、线性表
1.定义(informal)
同类型的有限个有序的线性集合
2.基本操作
创建销毁,判空、判长、打印输出
attn:①函数的命名,大驼峰②&使用场景:当在函数修改了值,要带回main()
3.顺序表
(1)存储结构
逻辑上相邻物理位置上也相邻
(2)实现方法
1)静态分配
2)动态分配
(3)特点
1)随机访问
直接取下边 O(1)
2)存储密度高
一个挨着一个
3)拓展容器不方便
得拷贝原小表到新的大表中 O(n)
4)插入、删除元素不方便
得移动前面or后面的其他元素 O(n)
(4)基本操作
a)插入
b)删除
4.单链表
(1)定义(informal)
自身data+指向下一个结点的pointer
(2)基本操作
见博客:
1)定义及初始化
2)判空、求表长
3)查找
a)按位序
b)按值
4)插入元素
a)指定结点的后插操作
b)指定结点的前插操作
5)删除
a)指定结点
b)替换技巧
6)摧毁链表
将L之后的结点依次删除,再free L
知识点:判空、后删、释放
(3)单链表的建立
1)尾插法
2)头插法
5.双链表
在单链表的基础上加上指向前一个结点的指针(prior)
(1)初始化
(2)插入(后插)
(3)删除(后删)
(4)遍历
1)前向遍历
2)后向遍历
4)查找
遍历+对比即可
1)按值查找
2)按位查找
6.循环链表
(1)循环单链表
在单链表的基础上,尾结点指向头结点
1)操作
a)初始化
b)判空
c)判头
d)判尾
e)插入删除
头部L头插;中间与单链表相同;尾部即尾插法
(2)循环双链表
在双链表的基础上,尾结点next指向头结点,头结点prior指向尾结点
1)操作
a)初始化
b)判空
c)判头
d)判尾
e)插入删除
头部L后插;中间同双链表;尾部相当于L前插
7.静态链表
不要求掌握代码,要求掌握定义和操作思路
(1)定义(informal)
结合了顺序表和单链表,先申请一段连续空间,结构体包括data和指向下一个结点的指针,但表示的是下一个结点的index
(2)操作
1)初始化
a[0] = -1//-1表示到头了
后面的设为-2//-2表示该结点为null
此处提供代码可以体会静态数组在内存中的实现方式,相当于SLinkList是个arr
#define MaxSize 10
typedef struct {
ElemType data;
int next;
}SLinkList[MaxSize];
2)查找
从前往后遍历 O(n)
3)插入
插入位序为i的结点e
step1:在空结点插入元素e
step2:从头开始遍历找到i-1个ele
step3:改变新插入结点的next指向i-1结点的next
step4:改变这一结点的next指向新插入结点的下标
4)删除
删除位序为i的结点
step1:查找第i-1个元素
step2:让i-1指向i的next
step3:i的next置空(改成-2)