2021.1.6学习

学习课程内容
陈老板讲课相当高深,只有哈希听明白了一点
B站学习
C语言链表尾插

> void insertNodeByTrall(struct Node *List,int data) {
>     struct Node *lastNode = endofList(List);
>     struct Node *newNode  = createNode(data);
>     lastNode->next = newNode; } struct Node* endofList(struct Node *List) {
>     while(List->next) List = List->next;
>     return List; }

以及其他链表内容

bool InsertList(linklist *HeadNode,int LocateIndex,int InData)

> {
>     int i=1;// 由于起始结点HeadNode是头结点,所以计数从1开始
> 
>     linklist *CurrentNode= (linklist *) HeadNode;
> 
>     //将CurrentNode指向待插入位置的前一个结点(index -1)
> 
>     while(CurrentNode&& i<LocateIndex-1)
> 
>     {
>         CurrentNode= CurrentNode->next;
> 
>         i++;
> 
>     }
> 
>     linklist *NodeToInsert=(linklist*)malloc(sizeof(linklist));
> 
>     if(NodeToInsert == NULL)
> 
>     {
>         printf("空间缓存不足");
> 
>         return ERROR;
> 
>     }
> 
>     NodeToInsert->Element= InData;
> 
>     NodeToInsert->next = CurrentNode->next;
> 
>     CurrentNode->next = NodeToInsert;
> 
>     return OK;
> 
> } bool DeleteList(linklist * HeadNode,int index, int * DataToDel)
> 
> {
>     int i = 1;
> 
>     linklist *CurrentNode  = HeadNode; 
> 
>     linklist *NodeToDelete;
> 
>     //将CurrentNode指向待删除位置的前一个结点(index -1)
> 
>     while(CurrentNode&& i<index-1)
> 
>     {
>         CurrentNode= CurrentNode->next;
> 
>         i++;
> 
>     }
> 
>     NodeToDelete = CurrentNode->next;
> 
>     *DataToDel =NodeToDelete->Element;
> 
>     CurrentNode->next= NodeToDelete->next;
> 
>     free(NodeToDelete);
> 
>     return OK;
> 
> } 

关于DFS的非队列尝试

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
int i,j,n,m1,m2,m3,k,step,s,a[1000000];
int find(int n,int k){
    while(1){
        if(n==k)
            return step;printf("%d ",n);
        step++;
        if(n>1&&a[n-1]==0){
            m1=n-1;
            a[m1]=1;


        }
        if(n<=k&&a[n+1]==0){
            m2=n+1;
            a[m2]=1;


        }
        if(n<=k&&a[n*2]==0){
            m3=m3*2;
            a[m3]=1;


        }find(m1,k);find(m2,k);find(m3,k);
        if(a[n]==1)
            return;
    }
}

int main(){
    scanf("%d %d",&n,&k);
    memset(a,0,sizeof(a));
    step=0;
    a[n]=1;
    s=find(n,k);
    printf("%d",s);
    return 0;
}

及关于该解法的试想
用三个函数进行递归检索

以下为引用课程大纲内容

图与搜索 状态空间和图(树) 树的前中后序遍历与层序遍历 dfs遍历图与求连通块 bfs遍历图与求最短路 数据结构 二叉树,二叉堆
二叉树的基本形态:空,仅左子树,仅右子树,有左右子树 二叉树的类别: 真二叉树:所有节点的度都要么为0,要么为2。
满二叉树(完美二叉树):所有节点的度要么为0,要么为2,且所有的叶子节点都在最后一层。
完全二叉树:叶子节点只会出现在最后2层,且最后一层的叶子节点都靠左对齐。 堆是完全二叉树 二叉树的基本性质 第 ii 层的节点数最大为
2^{i-1},i\geq12 i−1 ,i≥1 最大深度为 kk 层的二叉树最多有 2^k-12 k −1 个节点, k\geq
1k≥1 二叉树的几种遍历方法 先序遍历:根节点,左子树,右子树 中序遍历:左子树,根节点,右子树 后序遍历:左子树,右子树,根节点
层序遍历:从上到下,从左到右 二叉搜索树(二叉查找树) 静态查找问题可以使用二分法,使数据有序之后转化为了在树上的查找
O(log_2n)O(log 2 ​ n) 对于动态查找,能否直接使用树形结构存储数据呢?
对任意树上的节点来说,它的值比所有左子树的大,比所有右子树的小。 删除节点 是叶子节点 只有一个子节点 有两个子节点
特殊情况会退化成链状,即斜二叉树

  • 平衡二叉树,任意节点左右子节点高度差绝对值不超过 11 堆排序 小根堆:每个节点都小于他的左右子节点 完全二叉树的存储 两个基本操作:向下调整和向上调整 删除最小值操作为什么要与尾节点交换?和堆的储存方式相关 建堆 哈希表 普通的哈希表写法
    作用:把一个大的值域空间映射到一个较小的空间。 [0,N][0,N],NN 取 10^510 5 ~ 10^610 6
    例如,进行 nn 次操作,每次给出一个位于 [-109,109][−10 9 ,10 9 ]
    的数,每次操作是将这个数插入集合或是判断是否已经在集合中存在 设计一个函数满足 h(x) \subset
    [0,10^5]h(x)⊂[0,10 5 ],x\subset [-109,109]x⊂[−10 9 ,10 9 ]
    ,这个函数就被成为哈希函数 这个函数如何设计? 用于取模的数尽量选用质数,并且尽量离 22
    的整次幂尽可能的远,可以证明这种情况哈希冲突的概率最小。 显然存在冲突(不同的 xx 得到的 f(x)f(x) 值相同),该怎么办? 拉链法
    开一个 10^510 5 长度的数组,每一个“槽”拉一条链存储元素。
    虽然每一个“槽”都拉了一条链,但是在平均情况下来看,这条链的长度可以看作是常数,在一般情况下,哈希表的时间复杂度都是 O(1)O(1) 的。
    一般在哈希表的应用中,不需要考虑删除操作。 添加元素 开放寻址法 数组的长度需要为题目数据范围的2~3倍。 添加元素 查找元素 删除元素
    字符串哈希方法(字符串前缀哈希法) 预处理出所有前缀的哈希,特别的 h[0]=0h[0]=0 将整个字符串看作是一个 pp
    进制数,h(“ABCD”)=h((1234)_P)=h(1p3+2*p2+3p1+4*p0)=x%Qh(“ABCD”)=h((1234)
    P ​ )=h(1∗p 3 +2∗p 2 +3∗p 1 +4∗p 0 )=x%Q
    通过这种方式将字符串转化成了一个数字,由于计算出的数很大,需要mod一个数 QQ。 不能有字母映射成 00 。
    字符串哈希不考虑冲突情况,假定RP足够好不遇到冲突。 当 p=131p=131 或 p=13331p=13331 且 Q=2^{64}Q=2
    64 时,基本上认为不会发生冲突。 为什么选用前缀哈希? 可以利用公式计算出子串的哈希值。(左边是高位,右边是低位) 并查集
    每个点保存其父节点的信息 合并两个集合、查询两个元素是否在同一个集合 暴力:开数组保存元素属于的集合编号,查询 O(1)O(1),合并
    O(n)O(n) 并查集:用树形结构保存集合,根节点编号作为集合编号,保存每个节点的父节点信息 Q:如何判断树根? Q:如何取得集合编号?
    Q:如何合并两个集合? 此时的复杂度,查询 O(n)O(n),合并 O(1)O(1),如何优化(即降低树的高度)?
    注:合并操作前需要先查询根节点信息,此处的“合并”未计算查询复杂度 加入路径压缩优化,查询
    O(logn)O(logn),合并O(1)O(1) 加入按秩合并优化,查询 O(logn)O(logn),合并O(1)O(1)
    加入上述两种优化,查询 O(\alpha(n))O(α(n)),合并O(1)O(1) 近似认为其查询操作的时间复杂度
    O(\alpha(n)) = O(5) = O(1)O(α(n))=O(5)=O(1)
  • 由于阿克曼函数 f (n) = A(n, n)f(n)=A(n,n) 的增加速率非常快,因此其反函数 f^{−1} = \alphaf −1 =α 会以非常慢的速度增加。阿克曼反函数常用 αα 表示。因为 A(4, 4)A(4,4) 的数量级约等于\large
    2{{2{{10^{{19729}}}}}}2 2 10 19729
    ,因此对于一般可能出现的数值 nn,α(n)α(n) 均小于 55。 字典树 最大异或对 树状数组

前缀和

  • 每个数组下标代表一个前缀, 值为前缀的和, 然后用数组元素间做减法算出某个区间的和.填例子
  • 填题目

差分

  1. 保存相邻值的差.例子:每个数组下标代表一个前缀和, 上一个数组下标代表的前缀和 与 当前数组下标代表的前缀和 之差, 作为当前数组元素的值.(区间插气球问题)
  2. 填题目
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值