day01
数据结构与算法
数据结构是为算法服务的
- 算法是解决问题的思路和方法,是独立存在的
算法有三个特征:
- 必须要有一个结果
- 有穷性
- 可行性
两种基本的算法设计模型
- 贪心法 贪婪算法
- 枚举法:必须找到一个最优解
伪代码:就是用来解决问题的思路
- 包括:你的自然语言 数学表达形式 不纠结与你的具体编程语言形式
算法分析:
- 任何算法的实施必定消耗时间和空间上的资源
时间复杂度:
- 最坏时间复杂度,最优时间复杂度,平均时间复杂度
面试题:
- 如果 a+b+c = 1000,并且a^2 + b^2 = c^2 (a,b,c都是自然数),求a,b,c的组合有哪些
解析:一般算法: import time start_time=time.time() for a in range(1,1001): for b in range(1, 1001): for c in range(0, 1001): if a+b+c==1000 and a**2+b**2==c**2: print(a,b,c) end_time=time.time() print('time:%d'%(end_time-start_time)) print('结束') 减少遍历次数节省时间算法: import time start_time=time.time() for a in range(1,1001): for b in range(1, 1001): c = 1000-a-b if a**2+b**2==c**2: print(a,b,c) end_time=time.time() print('time:%d'%(end_time-start_time)) print('结束')
- a = (0,n) b(0,n) c(0,n)
- 0(n) = n*n*n*2
- 0(n) = n*n*n*7
- 最终的时间复杂度和你的规模n有关系
时间复杂度的几条基本计算规则
- 只有常数项,时间复杂度表示为0(1)
- 顺序结构,时间复杂度按加法计算
- 循环结构,按乘法计算
- 分支结构,取最大值
只关注操作数的最高次项,其他次要项和常数项不考虑
3 O(1)
2n+3 O(n)
3n**2+2n+3 O(n**2)
5log2N O(logn)
2n+3nlog2n+19 O(nlogn)
6n**3+2n**2+3n+2 O(n**3)
2**n O(2**n)
O(1)<O(logN)<O(n)<O(nlogn)<O(N**2)<O(N**3)<O(2**N)<O(N!)<O(N**N)
day02
链表
- 二元组(元素域 elem 链接域 next)
为了掌握一个单链表,只需要用一个变量来保存这个表的首结点应用
- (表头指针,表头变量) p表示
class Node (object):
def __init__(self,item):
#存储数据元素
self.item = item:
#链接域存储下个结点的位置信息
self.next = None
创建空链表
删除链表:
加入元素:头部插入,一般性插入
删除元素:删除表头结点 删除其他结点
Josephus 问题
假设有n个人围坐在一起,现在要求从k个人开始报数,报n个数,报到的人自动退出,从下一个人重新开始报数,按照同样的规则来进行,直至所有人全部退出,要求按顺序输出各出列人的编号
基本的算法思路
- 建立一个包含n个人的编号的表
- 找到第k个人,从那里开始
def josephus_A(n,k,m):
#给人员编号
people = list(range(1,n+1))
i = k-1
#循环操作
for num in range(n):
#为了计数
count = 0
while count < m:
if people[i] > 0:
count +=1
if count ==m:
print(people[i],end="")
people[i] = 0
i = (i+1)%n
if num <n-1:
print(", ",end="")
else:
print("")
return
josephus_A(41,1,3)
day03
数据结构
一.课前准备
- 数据:所有能被记录到计算机中并且能被计算机处理的符号的集合.
- 数据类型:数,字符串 ...
- 数据结构:计算机存储和组织数据的方式.
- 算法:计算机为解决特定的问题而产生的一系列解决问题的指令,简而言之,就是解决方案的准备完整的描述
二.目标
- 数据结构:理解逻辑结构,物理结构
- 算法:排序算法,查找算法
三.正文
逻辑结构:
- 概念: 数据之间(与计算机无关)的关系
- 主要分类:线性结构和非线性结构
其中非线性结构包括:
集合结构,树状结构,网状结构
- A.线性结构的特点
- 结构中必须存在唯一的首元素
- 结构中必须存在唯一的尾元素
- 除首元素外,结构中每一个元素有且只有一个前驱元素
- 除尾元素外,结构中每一个元素有且只有一个后继元素
- B.集合结构的特点:
- 无序性
- 互异性
- 确定性
- C.树状结构的特点
- 结构中必须存在唯一的一个根节点(根元素)
- 除根元素外,结构中每一个元素有且只有一个前驱元素
- 除叶元素外,结构中每一个元素拥有一个或多个后续元素
树状结构中的数据具有一对多的父子关系
- D.网状结构的特点
- 结构中每一个元素都可以拥有任意数量的前驱元素和后继元素
- 结构中任意两个元素之间都可以建立互联
网状结构中的数据具有多不多的交叉映射关系
- A.线性结构的特点
物理结构:
- 概念:数据具体在计算机内存中的存储方式.
- 分类:顺序存储结构,链式存储结构
详细介绍:
- 顺序存储
是将逻辑上相邻的元素放在物理内存也是相邻的存储单元中
优点:
1)节省存储空间,只需要为每个数据本身分配存储空间,不需要占用额外的空间来表示元素间的逻辑关系
2)方便随机存取元素
缺点:
1)连续的存储会降低空间的使用率
2)任意位置增加或者删除数据时操作复杂 - 链式存储
是使用不连续的存储空间来存放结构中的数据,将每个元素构造一个节点,节点中除了存放元素本身外,还需要存放下一个节点的地址
优点:
1)提高空间的使用率
2)任意位置增加或者删除数据时操作方便
缺点:
1)总体的空间开销比顺序存储要大
2)不方便随机的存取元素
数据源:ABCDEF...
内存中顺序:ABCDEF...
两者间关系:
- 每一种逻辑结构采用哪种物理结构来实现是没有规定.
所以,
基于顺序存储实现的表结构:顺序表
基于链式存储实现的表结构:链表
三.实战
- 顺序表
动态开辟内存空间 - 链表
- 基本特征
- 每一个数据放在一个独立的存储区
- 还需保证结构中任一结点可以找到与其相关联的下一结点
- 前一节点用链接方式显示的记录下一个节点之间的关联
- 基本两种形式
- 单链表:即单向链表
- 其每个节点包含数据元素
- 每个结点保存指向下一结点的链接
- 链表的尾节点的链接域为空,None
- 双链表:
- 其每个节点包含数据元素
- 每个结点保存指向下一结点的链接
- 每个结点保存指向前一结点的链接
- 链表的首节点的上一结点链接域为空,None
- 链表的尾节点的下一结点链接域为空,None
- 单链表:即单向链表
- 基本特征
四.容器
- 栈
基本特征:- 只能在一端增加和删除元素,这一端称为栈顶,另一端称为栈底
- 两个基本操作压人数据push 和弹出pop,弹出数据相当于删除最后插入的数据,也就是说栈实现的是一种 后进先出 的运算方式
- 从空栈中弹出数据和向满栈压入数据都视为一种错误
具体实现- 基于顺序存储的栈实现
- 基于链式存储的栈实现
- 队列
基本特征:- 队列可以两端增删数据,增加元素的一端称为后端,删除数据的一端称为前端
- 队列的基本操作同样是压人数据和弹出数据,前者相当于插入数据,后者则是删除最后先插入的数据,也就形成了 先进先出 的运算规则
- 在空队列中弹出数据和在满队列压入数据都视为一种错误
- 通常最先和最后插入的元素分别称为队首和队尾来被外界访问
具体实现- 基于顺序存储的队列实现
- 基于链式存储的队列实现
使用链式存储的队列没有实质上的技术困难,但是链式结构在两端进行操作需要消耗较长时间,并不适合队列的实现。
五.二叉树
- 二叉树是一种最简单的树状结构,其特点:
- 树中每个结点最多关联两个后继结点,也就是说,一个结点关联的结点数可为1 / 2 / 0.
- 每个结点关联的后继结点明确的分为左关联结点和右关联结点
- 基本概念
- 叶结点:二叉树中没有子节点的称为树叶,即叶结点
- 分支结点:树种除了叶结点外其余结点均为分支结点,其有一个或者两个分支
- 父结点:二叉树中根节点称为该树的节点
- 子节点:相应的,子树的根节点就是二叉树的子节点
- 满二叉树:每一层结点达到最大值,所有分支结点都有左右两个分支
- 完全二叉树:除了最下层的节点都达到最大值,且最下层的节点都连续集中在左侧
六.算法
- 查找算法
- 顺序查找
基本思路:从第一个元素开始,逐个与要查找的元素进行对比,若比较到两者的值相同时,则返回找到的元素下标值:若没有找到,则返回-1
评价:
若数据量较大时,查找长度变大,效率低
顺序查找对于数据的有序性没有要求. - 二分查找
a.二分查找也称为折半查找,属于有序查找的算法.
b.基本思路:用给定要查找的数据与中间数据进行对比,若相等则查找成功,若不相等,根据key 与中间数据的比较结果在其左子表或者右子表中继续递归查找,直到找到或者表中无该数据为止
c.评价:
要求数据必须是有序的,如无序数据,先排序后使用
因为二分查找每次将查找范围减少一半,缩短时间,
其时间复杂度是对数级,空间复杂度为常数级
- 排序算法
- 冒泡排序
基本思路:- 相邻元素俩俩相比,前者大于后者则交换
- 第一次遍历,从第一对数据到最后一对数据,将最大值上浮到顶端
- 后面继续将未排序的部分重复上步骤,依次上浮次最大值
- 每次扫描元素越来越少,直到不再发生交换为止
评价:
时间复杂度O(n2),空间复杂度O(1)
冒泡排序算法对于数据本身的有序性非常铭感
- 插入排序
基本思路:- 首元素自然有序
- 取出下一个元素,对已排序的序列从后向前扫描
- 若扫描的有序数据大于被取出的元素,则该有序数据后移
- 若扫描的有序数据小于被取出的元素,在该有序数据后面插入被取出的元素
- 若扫描的所有有序数据都大于被取出的元素,则在有序数据的头部插入被取出的元素
- 再取出下一个元素,继续重复之前的步骤,直到所有元素都有序为止
评价:时间复杂度:O(n2) 空间复杂度O(1)
- 快速排序
算法描述:- 从待排序的序列中任意选择一个基准
- 将所有小于基准的元素,等于基准所有元素,大于基准的元素进行分组,小于部分放前面,大于部分放后面
- 再以递归的方式,对基准之前和基准之后的分组继续上操作,直到每个组内的元素不多于一个为止
评价:
时间复杂度:O(nlogn)
若每次都能均匀分组则,快速排序速度是最快的.
所有示例