在线脑图:https://www.processon.com/view/link/617aa00f07912943dd03d4f4

开发环境

Mac C语言环境配置

软件:Visual Studio Code

Coder Runner 插件 :目的是为了实现在Visual Studio Code中 运行C语言代码

一、数据结构的概述

1、定义

我们如何把现实中大量而复杂的问题以特定的数据类型特定的存储结构保存到主存储器(内存)当中,以及在此基础上为实现某个功能(比如查找某个元素,删除某个元素,对所有元素进行排序)而执行的相应操作,这个相应的操作也叫算法

狭义:

​ 数据结构是专门研究数据存储问题

​ 数据的存储包含两方面:个体的存储+个体关系的存储

广义:

​ 数据结构既包含数据的存储也包含数据的操作

​ 对存储数据的操作就是算法

数据结构 = 个体 + 个体的关系

算法 = 对存储数据的操作

2、算法

什么是算法?

广义:算法是对存储对象的操作

狭义:指的是解决问题的方法和步骤

解题的方法和步骤

如何衡量算法的标准?

1、时间复杂度:程序大概要执行的次数,而非执行的时间

2、空间复杂度:算法执行过程中大概所占用的最大内存

3、难易程度

4、健壮性

3、数据结构的地位?

数据结构是软件中最核心的课程

程序 = 数据的存储 + 数据的操作 + 可以被计算机执行的语言

4、数据存储有几种结构?

1、线性结构

  • 连续存储【数组】

    • 优点:存储速度快

    • 缺点:插入删除元素时很慢

      ​ 空间有限制

      ​ 事先必须知道数组的长度

      ​ 需要大块连续存储块

  • 离散存储【链表】

    • 优点:空间无限制
    • 缺点:存储速度慢
  • 线性结构的应用----【栈】

  • 线性结构的应用----【队列】

2、非线性结构

二、预备知识

1、指针

(1)、指针的重要性:C语言的灵魂

(2)、定义:

  • 地址:

    • 内存的存储编号(门牌号)
    • 从0开始的非负整数
    • 范围:0 --> FFFFFFFFF【0-4G-1】
  • 指针:
    • 指针就是地址,地址就是指针
    • 指针变量是存放内存单元的地址的变量
    • 指针的本质是一个操作受限的非负整数

2、结构体

(1)为什么会出现结构体?

为了表达一些复杂的数据,普通的基本类型变量无法满足要求,结构体由此诞生!

(2)什么叫结构体

结构体是用户根据我们实际需要可自己定义的复合数据类型

(3)注意事项:

3、动态内存的分配和释放

4、递归

一、递归原理分析

(1)递归的定义

(2)分治法

(3)函数调用过程

(4)递归与栈

用阶层问题分析递归与栈

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RWriEn7a-1636795139579)(https://tva1.sinaimg.cn/large/008i3skNgy1gvypqofp7kj31600u0gry.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8iHFRanF-1636795139580)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyptu8i2qj31l60r6n13.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o76SwMmF-1636795139581)(https://tva1.sinaimg.cn/large/008i3skNgy1gvypvc0qdhj31pk0tedkq.jpg)]

二、相关应用

(1)求阶层

#include<stdio.h>
// 求n的阶层
long getJC(long n){if(n==1){return 1;}else{return getJC(n-1) * n;}}
int main(){printf("result=%ld",getJC(20));return 0;
}

(2)1+2+3+…+100的和

#include<stdio.h>
// 求1到100的和
long getSum(long n){if(n==1){return 1;}else{return getSum(n-1) + n;}}
int main(){printf("sum=%ld",getSum(100));return 0;
}

(3)走迷宫

(4)汉诺塔

函数的调用

当一个函数的运行期间调用另一个函数,在运行背调函数之前,系统需要完成三件事:

1)、将所有的实际参数返回地址等信息发送给被调函数

2)、 为被调函数的局部变量(也包括形参)分配内存空间

3)、将控制转移动到被调函数的入口,分配空间

从被调函数返回主调函数,系统也要完成三件事:

1)、保存被调函数的返回结果

2)、释放被调函数所占的存储空间

3)、依照被调函数保存的返回地址将控制转移到主调函数的地方

递归的应用

数和森林就是以递归的方式定义的

数和图的很多算法都是以递归来实现的

很多数学公式都是以递归的方式来定义的

三、线性结构

什么是线性结构?

可以用一根线把所有节点串起来,否则为非线性结构(树、图)

1、顺序表

(1)什么叫数组?

​ 元素类型相同,大小相等

(2)数组的优缺点?

自创数组

#include<stdio.h>
#include<mm_malloc.h>
#include<stdlib.h> // 包含了exit();
/*模拟数组
*/// 定义了一个数据类型,该数据类型的名字叫struct Arr,含有三个成员,分别是pBase,len,cnt
struct Arr{int *pBase; // 存储的是数组第一个元素的地址int len; // 数组所能容纳的最大元素个数int cnt; // 当前数组有效元素的个数
};/*
所有声明
*/
void initArr(struct Arr *pArr, int length);
bool isEmpty(struct Arr *pArr);
void showArr(struct Arr *pArr);
bool appendArr(struct Arr *pArr ,int val);
bool insertArr(struct Arr *pArr ,int pos,int val);
bool isFull(struct Arr *pArr);
bool deleteArr(struct Arr *pArr ,int pos,int *pVal);
void inversionArr(struct Arr *pArr);
void softArr(struct Arr *pArr);/*
主函数
*/
int main(){// int val;// 用于接收删除元素的值struct Arr arr;  // 定义一个变量arr,目前没有内容initArr(&arr,6);// printf("%d\n",arr.len);// showArr(&arr);// printf("\n---------------------\n");// appendArr(&arr,1);// appendArr(&arr,2);// appendArr(&arr,3);// appendArr(&arr,4);// appendArr(&arr,5);// appendArr(&arr,6);// appendArr(&arr,7);// showArr(&arr);// printf("\n---------------------\n");// insertArr(&arr,6,99);// showArr(&arr);// 测试deleteArr()// appendArr(&arr,1);// appendArr(&arr,2);// appendArr(&arr,3);// appendArr(&arr,4444);// appendArr(&arr,5);// appendArr(&arr,6);// showArr(&arr);// printf("\n---------------------\n");// deleteArr(&arr,4,&val); // val为用于接受所删除数据的值// printf("被删的元素值为:%d\n",val);// showArr(&arr);// 实现倒置// appendArr(&arr,1);// appendArr(&arr,2);// appendArr(&arr,3);// appendArr(&arr,4);// appendArr(&arr,5);// appendArr(&arr,6);// inversionArr(&arr);// showArr(&arr);// printf("\n---------------------\n");// 实现升序排序printf("\n---------------------\n");appendArr(&arr,2);appendArr(&arr,7);appendArr(&arr,5);appendArr(&arr,4);appendArr(&arr,8);appendArr(&arr,3);softArr(&arr);showArr(&arr);return 0;}/*初始化
*/
void initArr(struct Arr *pArr, int length){pArr->pBase = (int *)malloc(sizeof(int) * length); //pArr 这个指针变量所指向的那个结构体变量中的pBaseif(NULL == pArr->pBase){printf("动态内存分配失败!\n");exit(-1); // 终止挣个程序}else{pArr->len = length; // 数组所能容纳的最大元素个数pArr->cnt = 0;}return;
}/*显示输出
*/void showArr(struct Arr *pArr){if(isEmpty(pArr)){printf("数组为空\n");}else{for (int i = 0; i < pArr->cnt; i++){printf("%d  ",pArr->pBase[i]); printf("\n");}}
}/*判断数组是否为空
*/
bool isEmpty(struct Arr *pArr){if (0 == pArr->cnt){return true;}else{return false;}
}/*追加
*/
bool appendArr(struct Arr *pArr ,int val){// 满了 不能追加if(isFull(pArr)){return false;}// 不满的时候可以追加   : 1、 流程 2、功能 3、试错pArr->pBase[pArr->cnt] = val;pArr->cnt++;return true;
}
/*判断是否已满
*/
bool isFull(struct Arr *pArr){if(pArr->len  == pArr->cnt){printf("已满\n");return true;}else{return false;}
}bool insertArr(struct Arr *pArr ,int pos,int val){// 1、判断是否已满,如果已满则不能插入if(isFull(pArr)){return false;}// 2、再判断是否越界if(pos <1 || pos>pArr->cnt+1){return false;}for(int i = pArr->cnt-1; i>=pos-1; i--){pArr->pBase[i+1] = pArr->pBase[i]; // 把最后一个 给 最后一个的下一个}pArr->pBase[pos-1] = val; // 插入pArr->cnt++; // 有效个数加1return true;
}bool deleteArr(struct Arr *pArr ,int pos,int *pVal){if(isEmpty(pArr)){printf("数组为空\n");return false;}if(pos<1 && pos>pArr->cnt){printf("范围异常");return false;}// 先找到这个值*pVal = pArr->pBase[pos-1];// 开始删除for(int i = pos; i<pArr->cnt; i++){pArr->pBase[i-1] = pArr->pBase[i];}pArr->cnt--;// 有效个数减1return true;
}void inversionArr(struct Arr *pArr){int i=0; //第一个int j=pArr->cnt-1; // 最后一个int temp;while (i<j) // 值互换{   temp = pArr->pBase[i];pArr->pBase[i] = pArr->pBase[j];pArr->pBase[j] = temp;i++;j--;}return;}void softArr(struct Arr *pArr){// 选择排序int temp;for(int i =0; i<pArr->cnt; i++){for(int j=i+1; j<pArr->cnt;j++){if(pArr->pBase[i]>pArr->pBase[j]){temp = pArr->pBase[i];pArr->pBase[i] = pArr->pBase[j];pArr->pBase[j] = temp;}}}}

2、链表

预备知识-typedef关键词

目标:手敲链表

1、

#include<stdio.h>
typedef int QQ;  //为int 从新多去一个名字 int = QQ
typedef struct Student{int sid;char name[100];char sex;
}St; // St  等同于struct Studentint main(){int i = 10;QQ j = 10; // QQ等同于intprintf("%d %d",i,j);struct Student st;struct Student *ss;St st; // St st 等价于 struct Student st;St *ss; // St *ss等价于struct Student *ss;return 0;
}

2、

#include<stdio.h>typedef struct Student{int sid;char name[100];char sex;
}*St; // *St 等同于struct Student *int main(){   return 0;
}

3、

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3X8vxHbp-1636795139582)(https://tva1.sinaimg.cn/large/008i3skNgy1guxvs7qj1ej61j70u0gp702.jpg)]

(1)定义

1、N个节点离散的

2、彼此通过指针项链

3、每一个节点只可能有一个前驱节点,每个节点后面只可能有一个后驱节点。收节点没有前驱节点,尾结点没有后驱节点

专业术语:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3FrZlmm2-1636795139582)(https://tva1.sinaimg.cn/large/008i3skNgy1guxwgf3wunj61h00c440f02.jpg)]

**首节点 :**第一个有效节点

**尾结点:**最后一个有效节点

头结点:第一个有效节点之前的节点

​ 头结点并不存放有效数据

​ 加头结点的目的主要是为了方便对链表的操作

​ 头结点的数据类型和首结点一样

**头指针:**指向头结点的指针变量

**尾指针:**指向尾结点的指针变量

我们确定一个链表需要几个参数????

只需要一个参数:头指针,因为我们通过头指针可以推算出链表的其他所有信息

(2)分类

1、单链表

2、双链表:每一个节点有两个指针

3、循环链表:能通过任何一个节点找到其他所有的节点

4、非循环链表:

(3)算法

算法有两个标准,一个是广义的,一个是狭义的,从狭义的讲,算法跟数据的存储是有关系的,广义的讲,则

是无关的。

泛型:

利用某种技术达到的效果就是:不同的存储方式,执行的操作是一样的

注:狭义与广义区别

  • 狭义:从内部的真正实现上说
  • 广义:

怎么学算法?

涉及数学相关,把答案拿出来,把答案看懂!

如何将一个程序(答案)由不懂到看懂?

  • 流程
  • 每个语句的功能
  • 试错

1、遍历

2、查找

3、清空

4、销毁

5、求长度

6、排序

7、删除节点

自创链表

#include<stdio.h>
#include<mm_malloc.h>typedef struct Node{int data; //数据域struct Node *pNext;
}NODE,*PNODE;//声明函数
PNODE create_list();
void traverse_list(PNODE pHead);
bool is_empty(PNODE pHead);
int getLenght(PNODE pHead);
bool insert_list(PNODE pHead,int pos,int val);
bool deleteList(PNODE pHead,int pos,int *val); // 第三个参数用于存储被删链表的数值
void softList(PNODE pHead); //排序
bool insertList(PNODE pHead,int pos,int val); //链表插入 ,pos从1开始
bool deleteList(PNODE pHead,int pos,int *pVal); int main(){PNODE pHead = NULL; //  等价于struct Node *pHead = NULL;pHead = create_list(); //create_list()功能: 创建一个非循环单链表,并将该链表的头结点的地址赋给pHeadtraverse_list(pHead);//traverse_list 遍历输出if (is_empty(pHead)){printf("链表为空!\n");}else{printf("链表不为空!\n");}int len = getLenght(pHead);printf("链表长度为:%d\n",len);printf("\n-------------\n");//测试排序// softList(pHead);// traverse_list(pHead);printf("\n-------------\n");//测试插入// insertList(pHead,4,520);// traverse_list(pHead);printf("\n-------------\n");//测试删除int val;if (deleteList(pHead,4,&val)){printf("删除成功,该元素的值为:%d\n",val);}else{printf("删除失败,您好删除的元素不存在\n");}traverse_list(pHead);return 0;}PNODE create_list(){// 分配了一个不存放有效数据的头结点PNODE pHead =  (PNODE)malloc(sizeof(NODE));//  if(NULL == pHead){printf("分配失败,程序终止!");exit(-1);}PNODE pTail = pHead;pTail->pNext = NULL;int len;int i; // 用来存放用户有效输入节点的个数int val; // 用来临时存放用户输入的节点的值printf("请输入您需要生成链表节点的个数:len=");scanf("%d",&len);for(i=0; i<len; i++){printf("请输入第%d个节点的值:",i+1);scanf("%d",&val);PNODE pNew = (PNODE)malloc(sizeof(NODE));if(NULL == pHead){printf("分配失败,程序终止!");exit(-1);}pNew->data=val;//    将生成的节点挂到pHead头指针上,如何挂?方法如下pTail->pNext = pNew;pNew->pNext = NULL;pTail = pNew;//  pTail指向将pNew所在结构体对象的地址}return pHead;
}void traverse_list(PNODE pHead){// 遍历输出PNODE p = pHead->pNext;while (p!= NULL){printf("%d ",p->data);p = p->pNext;}printf("\n");return;
}bool is_empty(PNODE pHead){if (pHead->pNext==NULL){return true;}else{return false;}}int getLenght(PNODE pHead){int len = 0;// 遍历输出PNODE p = pHead->pNext;while (p!= NULL){len++;p = p->pNext;}return len;
}// bool insert_list(PNODE pHead,int pos,int val);//冒泡排序/**/
void softList(PNODE pHead){int i,j;int temp;int len =getLenght(pHead);PNODE p,q;for (i=0,p=pHead->pNext; i<len-1; i++,p=p->pNext) // 外层循环,6个数,只需要比较5次{for(j=i+1,q=p->pNext; j<len; j++,q=q->pNext){if(p->data>q->data){ //类使用数组中a[i]>a[j]temp = p->data;p->data =q->data;q->data = temp;}}}return;
}// 在pHead所指向链表的第pos个节点的前面插入一个新的节点,该节点的值为val,并且pos的值是从1开始
bool insertList(PNODE pHead,int pos,int val){//pos的范围是否合法int i = 0;PNODE p = pHead;while (p!=NULL && i <pos-1) //这个循环的目的是让p指向pos的前面一个节点{p = p->pNext; // 最终p会指向i++;}if (p==NULL || i >pos-1){return false;}PNODE pNew =  (PNODE)malloc(sizeof(NODE));if(NULL == pNew){printf("分配失败,程序终止!");exit(-1);}pNew->data=val; //值存入//开始插入PNODE q = p->pNext; //q为中间变量p->pNext = pNew;pNew->pNext=q;return true;/*这三行为核心代码-详细分析可以看下方流程图PNODE q = p->pNext; //q为中间变量p->pNext = pNew;pNew->pNext=q;*/
}bool deleteList(PNODE pHead,int pos,int *pVal){//pos的范围是否合法int i = 0;PNODE p = pHead;while (p->pNext!=NULL && i <pos-1) //这个循环的目的是让p指向pos的前面一个节点{p = p->pNext; // 最终p会指向i++;}if (NULL==p->pNext || i >pos-1){return false;}//接受被删除节点所存储的数值*pVal = p->pNext->data;//开始删除PNODE q = p->pNext; // 先将要删除的元素存起来,以便后面释放空间p->pNext = p->pNext->pNext; // 所谓删除,就是将p指向要删除的元素的后面一个,然后将p的空间释放free(p);}

插入3行代码分析:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7VmcoK1w-1636795139583)(https://tva1.sinaimg.cn/large/008i3skNgy1guyrsvusnij617g0u00wh02.jpg)]

(4)循环链表

定义:一种头尾相连的链表(即:表中最后一个节点的指针域指向头结点,整个链表形成了一个环)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-82Q801CB-1636795139584)(https://tva1.sinaimg.cn/large/008i3skNgy1gvycbjmuluj31gc0aa0th.jpg)]

==优点:==从表中的任一节点出发都能找到表中其他节点。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ih5KKsSA-1636795139585)(https://tva1.sinaimg.cn/large/008i3skNgy1gvych8gfkoj31pi0rwwip.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-deD3G3Ll-1636795139586)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyciyb3j1j31ax0u0q7e.jpg)]

如何将带尾指针的两个循环链表合并?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S6JhcwTX-1636795139587)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyclyczpdj31660fs0ue.jpg)]

分析一下有哪些操作?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qDSC5XZZ-1636795139587)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyct7jw4kj31bi0i0dhx.jpg)]

(1)、先保留Ta的头结点:p = Ta->next

(2)、将Ta表的表尾接到Tb表的第一个有效节点:Ta->next =Tb->next->next;

(3)、释放Tb表的头结点:free(Tb->next);delete Tb->next;

(4)、Tb表的尾结点指向Ta表的头结点:Tb->next =p

(5)双向链表

1、定义:在单链表的每个节点里增加一个指向其直接前驱的指针域prior,这样链表中形成了有两个方向不同的链,故称为双向链表。

2、结构:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QkmgIcrY-1636795139588)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyd16o0n2j31l60j60ve.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3nG0iPH3-1636795139589)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyd4yzum8j31pa0d6gmn.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-12rWf49i-1636795139590)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyd5eoncbj31dm094jsk.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-riEDNJhO-1636795139590)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyd5t4xirj30ug0aamxh.jpg)]

双向链表的插入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lWnqpPgi-1636795139591)(https://tva1.sinaimg.cn/large/008i3skNgy1gvye28l89dj31at0u0q5s.jpg)]

(6)双向循环链表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qcAxoKSy-1636795139592)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyd75zg84j31o40lm77m.jpg)]

(7)顺序表与链表的比较

一、链表的优缺点:

优点:

1、节点空间可以动态申请和释放

2、删除和插入操作的时候只需要修改指针,而不需要移动元素

缺点:

3、存储密度小,原因是每个节点在存储数据本身的同时,还需要额外的存储它的后续节点和前驱节点的地址,占用的空间比较大

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rSqLIwNC-1636795139592)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyegifr3dj31b20iu76f.jpg)]

4、非随机存取结构,时间复杂度就提高了

什么是随机存取?

即:任意一个元素都可以通过下表获取到

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Obb5F049-1636795139593)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyekqhwkzj31g20u0wmp.jpg)]

(8)线性表的应用

1、线性表的合并

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Wb3SmXr-1636795139594)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyeqy4httj31ou0f2mzi.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2dVmhRGH-1636795139594)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyhx6j83kj30yg0fswg0.jpg)]

实现方式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zzJIY7og-1636795139595)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyi11kel3j31c60oodm6.jpg)]

2、有序线性表的合并

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w8XxypXY-1636795139596)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyes2xdiuj31ne0fegos.jpg)]

为什么是非递减有序排序?

因为可能存在重复元素

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RYvBi7Ql-1636795139597)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyi4u8vdkj31me0fugoi.jpg)]

顺序表实现有序表的合并:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2PZv55Uk-1636795139598)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyi8sloxjj31p60oo0zg.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9xy2qUKA-1636795139598)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyibbvnmsj31oe0o6dkq.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F3NErfLZ-1636795139599)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyicrsbz1j31fw04i0tr.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZgUkE5RB-1636795139600)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyidi138nj31em04cgmo.jpg)]

链表实现有序表合并

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fwjGttbK-1636795139601)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyilzayzej31ku0okn02.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hl4f9jMC-1636795139601)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyimqglvxj31ne0tadk7.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YLPVSulo-1636795139602)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyin3hwiqj31j40s40vw.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rOUIOxMg-1636795139603)(https://tva1.sinaimg.cn/large/008i3skNgy1gwbctsxtv1j31me0r841w.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2lIx6uEZ-1636795139604)(https://tva1.sinaimg.cn/large/008i3skNgy1gvyirvueagj31kc04u0ty.jpg)]

注:最坏情况就是La和Lb一样长,所有的都要执行完,所有时间复杂度是最大为

肝了一个月,全网最全的数据结构与算法知识总结相关推荐

  1. 【硬核】肝了一个月,Cisco网络工程师知识点总结

    [硬核]肝了一个月,Cisco网络工程师知识点总结 高能预警,本文是我一个月前就开始写的,所以内容会非常长,当然也非常硬核,有实验,有命令,所以才写到了现在. 我相信90%的读者都不会一口气看完的,因 ...

  2. 肝了一个月,整理了一万道2020年最新Java面试题,阿里offer有了

    肝了一个月的面试题终于来啦,大家开心不. 2020年最新Java面试题整理,全网最全一份,包含各个技术栈,Java基础,Java集合,多线程,Java异常,spring,spring MVC,spri ...

  3. 全网最全json数据结构可视化工具汇总

    全网最全json数据结构可视化工具汇总 1.前言 2. 可视化工具 2.1 JSON Viewer Pro(推荐) 2.2 JSONGrid(推荐) 2.3 json2html(推荐) 2.4 Onl ...

  4. 肝了一个月,我做了个免费的面试刷题网

    大家好,我是鱼皮. 如今找工作.面试实在是太卷了,每轮面试都 必考 八股文,不背不行.网上虽然有很多面试题,但过于分散,就导致很多朋友又不知道到哪去找题.该背哪些题了. 所以我决定做一个完全免费.干净 ...

  5. 肝了一个月,终于搞到了 30 页的 Python 进阶面试题

    聚焦国内外,各个企业都在广泛应用 Python.国外例如谷歌.NASA.YouTube.Facebook.工业光魔和红帽等:国内大厂有阿里.腾讯.豆瓣.搜狐.新浪.网易.百度.金山.盛大.热酷.土豆以 ...

  6. 我肝了一个月,给你写出了这本 Java 开发手册!

    作者 | cxuan 来源 | 程序员cxuan 超长预警!!全文4万多字,墙裂建议收藏! 先来看一下本篇文章的思维导图吧,我会围绕下面这些内容进行讲解.内容很干,小伙伴们看完还希望不吝转发. 下面开 ...

  7. 肝了一个月!这本 Java 开发手册出炉啦!

    大家好,我是久一. 今天推送一篇高质量博文,这篇文章一共 44330 字,超级全面的 Java 基础知识总结,图文并茂.如果需要 PDF 版本的,可以后台回复「开发手册」下载!作者是久一的好朋友 cx ...

  8. 肝了一个月的 DDD,一文带你掌握!

    整体阅读时间,在 30 分钟左右. 大家好,我是楼仔! 去年倒腾了一个半月,写过一篇 DDD 的文章,当时没有推广,完全自嗨,为了不让这篇好文被埋没,现重新整理,突出重点,可读性更强! 为了证明该文没 ...

  9. 肝了一个月的 DDD,一文带你掌握

    整体阅读时间,在 30 分钟左右. 大家好,我是楼仔! 去年倒腾了一个半月,写过一篇 DDD 的文章,当时没有推广,完全自嗨,为了不让这篇好文被埋没,现重新整理,突出重点,可读性更强! 为了证明该文没 ...

  10. 我肝了一个月,给你写出了这本Java开发手册。

    先来看一下本篇文章的思维导图吧,我会围绕下面这些内容进行讲解. 下面开始我们的文章. Java 概述 什么是 Java? Java 是 Sun Microsystems 于1995 年首次发布的一种编 ...

最新文章

  1. 吉大c语言程序设计作业一,吉林大学历年C语言程序设计试题及答案.doc
  2. android+4.4+img,重新打包boot.img时出错(Android)
  3. tensorflow官网视频教程
  4. python的自带数据集_解决Keras自带数据集与预训练model下载太慢问题
  5. 信息系统项目管理师一些重要问题和知识点
  6. 极光尔沃切片软件_极光尔沃3D打印机走进肥东中小学校
  7. 今天才知道,MySQL 的 binlog 编号可以这么大!
  8. linux添加物理卷编辑文件夹,Red hat Linux下的逻辑卷管理器LVM-上
  9. Nginx应用场景之动静分离
  10. python:ValueError: numpy.ufunc size changed, may indicate binary incompatibility. Expected 216 from
  11. 蓝桥杯 省赛 杨辉三角形 python组(转)
  12. rdkit GetAtoms获取化合物每个位置的索引;rdkit FindMCS大公共相同结构 找不同化合物之间的差异
  13. 伪原创文章实操方式。
  14. Python掷骰子游戏
  15. 微软五笔 v1.0 下载
  16. 微软2008年7月「最有价值专家」(MVP)当选名单
  17. oracle 动态声明变量_Oracle11g新特性之动态变量窥视
  18. 【转】ORA-28040: 没有匹配的验证协议
  19. 晨光科力普基于GitLab CI/CD持续集成服务的应用
  20. 数据结构之冒泡排序算法(图解+分析+代码调优)

热门文章

  1. iOS系统下常用的三方应用URL Scheme值
  2. 投影仪买哪个好?家用投影仪哪种好
  3. Kmplayer音频设置
  4. ci定位 lac_LAC、CI、小区、扇区、基站都是什么
  5. 家政上门预约服务小程序源码+前端后端
  6. 前端技术之babel转码器
  7. 如何在mac下安装win7
  8. 鸽群优化算法(Pigeon-inspired Optimization algorithm, PIO)附matlab代码
  9. 32位与64位到底什么区别?
  10. 什么叫做罗列式_申论作文写作之案例罗列式开头