数据结构基本概念
- 数据:数据即信息的载体,是能够输入到计算机中并且能被计算机识别,存储和处理的符号总称
- 数据元素:数据元素是数据的基本单位,又称之为记录。一般,数据元素由若干基本项(字段,域,属性)组成。
- 数据结构:数据结构指的是数据元素及数据元素之间的相互关系,或组织数据的形式
数据之间的结构关系
- 逻辑结构
- 表示数据之间的抽象关系(邻接关系,从属关系),按每个元素可能具有的直接前驱数和直接后继数将逻辑结构分为‘线性结构’和‘非线性结构’两大类
- 特点:
- 只是描述数据结构中数据元素直接的练习规律
- 是从具体问题中抽象出来的数学模型,是独立于计算机存储器的(与机器无关)
- 分类
- 线性结构:线性结构是N个数据元素的有序集合
- 树形结构:数据元素之间存在着”一对多“的树形关系的数据结构
- 图状结构:一种多对多的关系
- 其他结构
- 存储结构
- 逻辑结构再计算机中的具体实现方式,分为顺序存储方法,链接存储方法,索引存储方法,散列存储方法
- 特点
- 是数据的逻辑结构在计算机存储器中的映象
- 存储结构是通过计算机程序来实现的,因而是依赖于具体的计算机语言的
- 分类
- 顺序存储:将数据结构中各元素按照其逻辑顺序存放于存储器一片连续的存储空间中
- 链式存储:将数据结构中各元素分布到存储器的不同点,用记录下一个结点位置的方式建立他们之间的联系,由此得到的存储结构为链式存储结构
- 索引存储:在存储数据的同时,建立一个附加的索引表,即索引存储结构=数据文件+索引表
- 散列存储:根据数据元素的特殊字段(称为关键字key),计算数据元素的存放地址,然后数据元素按地段存放,所得到的存储结构为散列存储结构
线性表
- 线性表的顺序存储
- 定义:若将线性表中的各元素一次存储于计算机一片连续的存储空间,这种进制表示为线性的顺序存储结构
- 特点
- 逻辑上相邻的元素ai,ai+1,其存储位置也是相邻的
- 存储密度高,方便对数据的遍历查找
- 对表的插入和删除等运算的效率较差
- 线性表的链式存储
- 定义:将线性表中各元素分布再存储器的不同存储块,称为结点,每个结点(尾结点除外)中都持有一个指向下一个节点的引用,这样所得到的存储结构为链表结构
- 特点:
- 逻辑上相邻的元素,其存储位置也不一定相邻
- 存储稀疏,不必开辟整块存储空间
- 对表的插入和删除等运算的效率较高
- 逻辑结构复杂,不利于遍历
栈和队列
- 栈
- 定义:栈是限制再一段进行插入操作和删除操作的线性表,允许进行操作的一端称为栈顶,另外固定一段为栈底,当栈中没有元素时成为空栈
- 特点
- 栈只能在一端进行数据操作
- 栈模型具有后进先出的规律
- 队列
- 定义:队列是现在再两端进行插操作和删除操作的线性表,允许进行存入操作的一段称为队尾,允许进行删除操作的一段称为队头
- 特点
- 队列只能在队头和队尾进行数据操作
- 线模型具有先进先出的规律
树形结构
基础概念:有且只有一个根,其余结点分为互不相交的有限集合,并称为其根的子树
二叉树的遍历:沿着条搜索路径周游二叉树,再树中的每一个节点访问一次且仅访问一次
- 先序遍历:先访问树根,再访问左子树,最后访问右子树(根,左,右)
- 中序遍历:先访问左子树,再访问根,最后右子树(左,根,右)
- 后序遍历:先访问左子树,再访问右子树,最后访问根(左,右,根)
- 层次遍历:从根节点开始,组层从左向右进行遍历
递归思想和实践
递归函数是指一个函数的函数体中直接调用或间接调用了该函数自身的函数
递归函数调用的执行过程的两个阶段
- 递推阶段:从原问题出发,按递归公式递推从未知到已知,最终大刀递归终止条件
- 回归阶段:按递归终止条件求出结果,逆向逐步带入递归公式,回归到原问题求解
优缺点
- 优点:递归可以吧问题简单化,让思路更为清晰,代码更简洁
- 缺点:递归因系统环境影响大,当递归深度太大时,可能会得到不可预知的结果
排序和查找
排序:将无序的记录序列调整成有序的序列
常见的排序方法:
- 冒泡排序
- 选择排序
- 插入排序
- 快速排序
查找:是在给定信息集上寻找特点信息元素的过程
二分查找:当数据量很大适宜采用该方法,采用二分法查找时,数据需要是排好序的
网络编程基础
计算机网络功能主要是包括实现资源共享,实现数据信息的快速传递
OSI七层模型
作用:使网络通信工作流程标准化
优点:
- 建立了统一的工作流程
- 分部清晰,各司其职,每个步骤分工明确
- 降低了各个模块直接的耦合度,便于开发
- 应用层:提供用户服务,具体功能有应用程序实现
- 表示层:数据的压缩优化加密
- 会话层:建立用户级的连接,选择适当的传输服务
- 传输层:提供传输服务
- 网络层:路由选择,网络互联
- 链路层:进行数据交换,控制具体数据的发送
- 物理层:提供数据传输的硬件保证,网卡接口,传输介质
四层模型(TCP/IP模型)
背景:实际工作中工程师无法完全按照七层模型要求操作,逐渐演化为更符合实际情况的四层
- 应用层对应协议:TFTP,FTP,NPS,WAIS | Telnet ,Rlogin,SNMP,Gopher | SMTP,DNS
- 传输层对应协议:TCP,UDP
- 网际层对应协议:IP ,ICMP,RARP,AKP,UUCP
- 网络接口对应协议:PDDI,PDN.......
数据传输过程
- 发送端由应用层程序发送消息,逐层添加首部信息,最终在物理层发送消息包
- 发送的消息经过对个节点(交换机,路由器)传输,最终到达目标主机
- 目标主机由物理层逐层解析首部消息包,最终到应用程序呈现消息
网路协议
在网路数据传输中,都遵循的规定,包括建立声明样的数据结构,什么样的特殊标志等
网路基础概念
- 网路主机(host):标识一台主机再网络中的位置
- IP地址:确定一台主机的网络路由位置
- 域名:给网络服务器地址起的名字,方便记忆,表达一定含义
- 端口号(port):端口是网络地址的一部分,用于区分主机上不同的网络应用程序
传输层服务
- 面向连接的传输服务(基于tcp协议)
- 传输特征:提供了可靠的数据传输,可靠性指数据传输过程中无丢失,无失序,无差错,无重复
- 实现手段:在通讯前需要建立数据连接,通讯结束要正常断开连接
- 三次握手(建立连接)
- 客户端向服务器发送消息报文请求连接
- 服务器收到请求后,回复报文确定可以连接
- 客户端收到回复,发送最终报文连接建立
- 四次挥手(断开连接)
- 主动方发送报文请求断开连接
- 被动方收到请求后,立即回复,表示准备断开
- 被动方准备就绪,再次发送报文表示可以断开
- 主动方收到确定,发送最终报文完成断开
- 面向无连接的传输服务(基于UDP协议)
- 传输特点:不保证传输的可靠性,传输过程没有连接和断开,数据收发自由随意
- 适用情况:网络较差,对传输可靠性要求不高
socket套接字编程
套接字:实现网络编程进行数据传输的一种技术手段
套接字分类:
- 流式套接字:以字节流方式传输数据,实现tcp网络传输方案(面向连接--tcp协议--可靠的--流式套接字)
- tcp套接字服务端流程
- 创建套接字:sockfd=socket.socket(socket_family=AF_INET,socket_type=SOCK_STREAM,proto=0)
- 绑定地址:sockfd.bind(addr)
- 设置监听:sockfd.listen(n)
- 等待处理客户端连接请求:connfd,addr = sockfd.accept()
- 消息收发:data = connfd.recv(buffersize),n = connfd.send(data)
- 关闭套接字:sockfd.close()
- 客户端流程
- 创建套接字:注意:只有相同类型的套接字才能进行通信
- 请求连接:sockfd.connect(server_addr)
- 收发消息:注意: 防止两端都阻塞,recv send要配合
- 关闭套接字
- tcp套接字数据传输特点
- tcp连接中当一端退出,另一端如果阻塞在recv,此时recv会立即返回一个空字串。
- tcp连接中如果一端已经不存在,让然试图通过send发送则会产生BrokenPipeError
- 一个监听套接字可以同时连接多个客户端,也能够重复被连接
- 网络收发缓冲区
- 网络缓冲区有效的协调了消息的收发速度
- send和recv实际是向缓冲区发送接收消息,当缓冲区不为空recv就不会阻塞。
- tcp粘包
- 原因:tcp以字节流方式传输,没有消息边界。多次发送的消息被一次接收,此时就会形成粘包。
- 影响:如果每次发送内容是一个独立的含义,需要接收端独立解析此时粘包会有影响。
- 处理方法:1.人为的添加消息边界 2.控制发送速度
- 数据报套接字:以数据报方式传输数据,实现UDP网络传输方案
- UDP套接字服务端流程:
- 创建数据报套接字:sockfd = socket(AF_INET,SOCK_DGRAM)
- 绑定地址:sockfd.bind(addr)
- 消息收发:data,addr = sockfd.recvfrom(buffersize),n = sockfd.sendto(data,addr)
- 关闭套接字:sockfd.close()
- 客户端流程:
- 创建套接字
- 收发消息
- 关闭套接字
- tcp套接字和udp套接字编程区别
- 流式套接字是以字节流方式传输数据,数据报套接字以数据报形式传输
- tcp套接字会有粘包,udp套接字有消息边界不会粘包
- tcp套接字保证消息的完整性,udp套接字则不能
- tcp套接字依赖listen accept建立连接才能收发消息,udp套接字则不需要
- tcp套接字使用send,recv收发消息,udp套接字使用sendto,recvfrom
TCP套接字之HTTP传输
HTTP协议(超文本传输协议)
- 用途:网页获取,数据传输
- 特点:
- 应用层协议,传输层使用tcp传输
- 简单,灵活,很多语言都有HTTP专门接口
- 无状态,协议不记录传输内容
- http1.1支持持久连接,丰富了请求类型网页请求过程
- 网页请求过程
- 客户端(浏览器)通过tcp传输,发送http请求给服务端
- 服务端接收到http请求后进行解析
- 服务端处理请求内容,组织响应内容
- 服务端将响应内容以http响应格式发送给浏览器
- 浏览器接收到响应内容,解析展示
HTTP请求
请求行:具体的请求类别和请求内容 GET (请求类别) /(请求内容) HTTP/1.1(协议版本)
请求类别:每个请求内别表示要做不同的事情
- GET:获取网络资源
- POST:提交一定的信息,得到反馈
- HEAD:只获取网络资源的响应头
- PUT:更新服务器资源
- DELETE:删除服务器资源
- CONNECT
- TRACE:测试
- OPTIONS:获取服务器性能信息
请求头:对请求的进一步解释和描述
空行
请求体:请求参数或者提交内容
HTTP响应
响应格式:响应行,响应头,空行,响应体
响应行:反馈基本响应情况 HTTP/1.1(版本信息) 200(响应码) OK(附加信息)
响应码:
- 1xx:提示信息,表示请求被接收
- 2xx:响应成功
- 3xx:响应需要进一步操作,重定向
- 4xx:客户端错误
- 5xx:服务器错误
响应头:对响应内容的描述 Content-Type:text/html
响应体:响应的主体内容信息
多任务编程
意义:充分利用计算机多核资源,提高程序的允许效率
实现方案:多线程,多进程
并行与并发
- 并发:同时处理多个任务,内核再任务间不断的切换达到好像多个任务被同事执行的效果,实际每个时刻只有一个任务占有内核
- 并行:多个任务利用计算机多核资源在同时执行,此时多个任务间为并行关系
进程
定义:程序在计算机中的一次运行
- 程序是一个可执行的文件,是静态的占有磁盘
- 进程是一个动态的过程描述,占有计算机运行资源,有一定的生命周期
进程的基本概念:
- CPU时间片:如果一个进程占有cpu内核则称这个进程在cpu时间片上
- PCB(进程控制块):在内存中开辟的一块空间,用于存放进程的基本信息,也用于系统查找识别进程
- 进程ID(PID):系统为每个进程分配的一个大于0的整数,作为进程ID,每个进程ID不重复。Linux查看进程ID:ps-aux
- 父子进程:系统中每一个进程(除了系统初始化进程)都有唯一的父进程,可以有0个或多个子进程,父子进程关系便于进程管理
- 进程状态(三态)
- 就绪态:进程具备执行条件,等待分配cpu资源
- 运行态:进程占有cpu时间片正在运行
- 等待态:进程暂时停止运行,让出cpu
- 五态(在三态基础上增加新建和终止)
- 新建:创建一个进程,获取资源的过程
- 终止:进程接收,释放资源的过程
- 进程的运行特征:
- 进程可以使用计算机多核资源
- 进程是计算机分配资源的最小单位
- 进程之间的允许状态互不影响,各自独立
- 每个进程拥有独立的空间,各自使用自己空间资源
- 基于fork的多进程编程
- 实现看代码
- 孤儿和僵尸
- 孤儿进程:父进程先于子进程退出,此时子进程成为孤儿进程
- 特点:孤儿进程会被系统进程收养,此时系统进程就会成为孤儿进程新的父进程,孤儿进程退出该进程会自动处理
- 僵尸进程:子进程先于父进程退出,父进程又没有处理子进程的退出状态,此时子进程就会成为僵尸进程
- 特点:僵尸进程虽然结束,但是会存留部分PCB再内存中,大量的僵尸进程会浪费系统的内存资源
- 如何避免僵尸进程产生
- 使用wait函数处理子进程退出
- 创建二级子进程处理僵尸
- 通过信号处理子进程退出
- multiprocessing模块创建进程
- 流程特点
- 将需要子进程执行的事件封装为函数
- 通过模块的Process类创建进程对象,关联函数
- 可以通过进程对象设置进程信息及属性
- 通过进程对象调用start启动进程
- 通过进程对象调用join回收进程
- 进程池实现
- 必要性
- 进程的创建和销毁过程消耗的资源较多
- 当任务量众多,每个任务在很短时间内完成时,需要频繁的创建和销毁进程。此时对计算机压力较大
- 进程池技术很好的解决了以上问题
- 原理:
- 创建一个数量的进程来处理事件,事件处理完进程不退出而是继续处理其他事件,直到所有事件全都处理完毕统一销毁,增加进程的重复利用,降低资源消耗
- 创建进程池的步骤
- 创建进程池对象,放入适当的进程
- 将事件加入进程池队列执行
- 关闭进程池
- 回收进程池中进程
- 进程间通讯(IPC)
- 必要性:进程间空间独立,资源不共享,此时在需要进程间数据传输时就需要特定的手段进行数据通信
- 常见进程键通信方法
- 管道(Pipe):在内存中开辟管道空间,生成管道操作对象,多个进程使用同一个管道对象进行读写即可实现通信
- 消息队列:在内存中建立队列模型,进程通过队列将消息存入,或者从队列取出完成进程间通信
- 共享内存:在内存中开辟一块空间,进程可以写入内容和读取内容完成通信,单是每次写入内容会覆盖之前内容
- 本地套接字:用于本地两个程序之间进行数据的收发
- 套接字文件:用于本地套接字之间通信时,进行数据传输的介质
- 创建流程
- 创建本地套接字:sockfd = socket(AF_UNIX,SOCK_STREAM)
- 绑定本地套接字文件:sockfd.bind(file)
- 监听,接收客户端连接,消息收发:isten()-->accept()-->recv(),send()
- 信号量:给定一个数量对多个进程可见,多个进程都可以操作该数量增减,并根据数量值决定自己的行为
线程(Thread)
线程基本概念
- 什么是线程
- 线程被成为轻量级的进程
- 线程也可以使用计算机多核资源,是多任务编程方式
- 线程是系统分配内核的最小单元
- 线程可以理解为进程的分钟任务
- 线程特征
- 一个进程中可以包含多个线程
- 线程也是一个运行行为,消耗计算级内存
- 一个进程中的所有线程共享这个进程的资源
- 多个线程之间的运行互不影响各自运行
- 线程的创建和销毁消耗资源小于进程
- 各个线程也有自己的ID特征
- threading模块创建线程
- 创建线程对象:t = Thread()
- 启动线程:t.start()
- 回收线程:t.join([timeout])
同步互斥
- 线程间通信方法:线程间使用全局变量进行通信
- 共享资源争夺
- 共享资源:多个进程或者线程都可以操作的资源成为共享资源,对贡献资源的操作代码段成为临界区
- 影响:对共享资源的无序操作可能会带来数据的混乱,或者操作错误,此时往往需要同步互斥机制协调操作顺序
- 同步互斥机制
- 同步:同步是一种协作关系,为完成操作,多进程或者线程间形成一种协调,按照必要的步骤有序执行操作
- 互斥:互斥是一组制约关系,当一个进程或者线程占有资源时会进行加锁处理,此时其他进程线程就无法操作该资源,直到解锁后才能操作
- 线程同步互斥方法
- 线程Event
- 线程锁Lock
- 死锁
- 定义:死锁是指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一组阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁
- 死锁产生的原因
- 当前线程拥有其他线程需要的资源
- 当前线程等待其他线程已拥有的资源
- 都不放弃自己拥有的资源
- 如何避免死锁
- 使用定时锁
- 使用重入锁RLock(),用法同Lock,RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其它的线程才能获得资源
- python线程GIL
- python线程的GIL问题(全局解释器锁)
- 什么是GIL:由于python解释器设计中加入了解释器锁,导致python解释器同一时刻只能解释执行一个线程,大大降低了线程的执行效率
- 导致后果:因为遇到阻塞时线程会主动让出解释器,去接收其他线程,所以python多线程在执行多阻塞高延迟IO时可以提升程序效率,其他情况并不能对效率有所提升
- GIL问题建议
- 尽量使用进程完成无阻塞的并发行为
- 不适用c作为解释器(java C#)
- 结论:在无阻塞状态下,多线程程序和单线程程序执行效率几乎差不多,甚至还不如单线程效率。但是多进程运行相同内容却可以有明显的效率提升
进程和线程的区别联系
- 两者都是多任务编程方式,都能使用计算机多核资源
- 进程的创建删除消耗的计算机资源比线程多
- 进程空间单独,数据互不干扰,有专门通信方法,线程使用全局变量通信
- 一个进程可以有多个分支线程,两者有包含关系
- 多个线程共享进程资源,在共享资源操作时往往需要同步互斥处理
- 进程线程再系统中都有自己的特有属性标志,如ID,代码段,命令集
协程技术
- 定义:纤程,微线程。是为非抢占式多任务产生子程序的计算机组件,协程允许不同入口点再不同位置暂停或开始,简单来说,协程就是可以暂停执行的函数
- 协程原理:记录一个函数的上下文栈帧,协程调度切换时会将记录的上下文保存,再切换回来时进行调取,恢复原有的执行内容,以便从上一次执行位置继续执行
- 协程优缺点
- 协程完成多任务占用计算资源很少
- 由于协程的多任务切换再应用层完成,因此切换开销少
- 协程为单线程程序,无需进行共享资源同步互斥处理
- 缺点:协程的本质是一个单线程,无法利用计算机多核资源