程序=数据结构+算法(瑞士 尼克劳斯·威茨 提出)
数据结构:逻辑结构 和 物理结构
逻辑结构:集合结构、线性结构、树形结构、图形结构
物理结构:数据存储
数据元素的存储结构:顺序存储结构(地址连续的存储单元) 和 链式存储结构(任意存储单元,数据间使用指针关联)
算法的基本特性:
- 输入性 有零个或多个输入
- 输出性 至少有一个或多个输出
- 有穷性 算法在执行有限步后能自动结束,不会出现无限循环
- 确定性 算法的每一步都具有确定的含义,不会出现二义性
- 可行性 算法的每一步都能够通过执行有限操作完成
算法的复杂度: 时间复杂度(计算的时间) 和 空间复杂度(需要的内存空间)
度量时间复杂度: 大O表示法 O( ) 度量一个算法好坏的重要指标
时间复杂度基本计算规则:
- 基本操作,即只有常数项,时间复杂度为 O(1)
- 顺序结构,时间复杂度 按 加法计算
- 循环结构,时间复杂度 按 乘法计算
- 分支结构,时间复杂度取最大值 (if—elif—else)
- 判断一个算法的效率时,往往只需要关注 操作数量的最高次项,其他 次要项 和 常数项可以忽略
- 在没有特殊说明时,分析算法的时间复杂度 都是指 最坏时间复杂度
所消耗的时间从小到大:
O(1) < O(log n) < O(n) < O(n log n) < O(n2)**
时间复杂度怎么来判断(适用大部分情况)
O(1) 无论有多少数据,以及操作就可以得出结论
O(n) 跟你的数据成正比1:1 一个for循环
O(logn) 一次操作可以砍掉一半
O(n2) 更数据成正比1:2 两个for循环
数组:
时间复杂度:数组的查询O(1)),添加和删除O(n)
数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量,它可以存储一个固定大小的相同类型元素的顺序集合。
线性表:有限序列
线性表的基本特征:
- 第一个数据元素 没有前驱元素
- 最后一个数据元素 没有后继元素
- 其余每个数据元素 只有一个前驱元素和一个后继元素
线性表按物理存储结构:顺序表(顺序存储) 和 链表(链式存储)
顺序表的优缺点:
- 优点:支持随机访问
- 缺点:插入和删除操作需要移动大量的元素,造成存储空间的碎片
链表:合理运用空间
链表的查询效率O(n),删除效率,添加效率O(1)
- 单向链表:每个节点包含两个域,一个元素域 和 一个链接域(指向下一节点),最后一个节点的链接域为 None
- 单向循环链表:在单链表的基础上,最后一个节点的链接域 不为 None ,而是指向连接表的头节点
- 双向链接表:每个节点包含三个域,一个元素域 和 两个链接域 ,两个链接域 分别指向上一节点、下一节点,第一个节点 连前面节点的链接域写 0,最后一个节点,连后面节点的链接域写 0
栈:
仅允许 在一端进行删除或添加
后进先出
class Stack(object):
def __init__(self): 实例属性的初始化和赋值
self.stack=[ ]
def add(self,item): 向栈中添加元素
return self.stack.append(item)
def pop(self): 弹出 栈顶元素
if len(self.stack) == 0:
return None
else:
return self.stack.pop( )
def peek(self): 返回 栈顶元素
if len(self.stack) == 0:
return None
else:
return self.stack[-1]
def is_empty(self): 判断是否为空 空返回 True 不为空 返回 False
return self.stack == [ ]
def size(self): 查看长度
return len(self.stack)
s=Stack( )
print(s.pop( ))
print(s.peek( ))
print(s.is_empty)
p.add(1)
p.add(2)
p.add(3)
print(s.pop( ))
print(s.peek( ))
print(s.is_empty)
输出结果:None
None
True
3
2
False
队列:
一端进行插入,另一端进行删除
先进先出
class DuiLie(object):
def __init__(self): 实例属性的初始化和赋值
self.duilie=[ ]
def add(self,item): 添加元素
return self.duilie.append(item)
def pop(self): 删除元素
if len(self.duilie) == 0:
return None
else:
retturn self.duilie.pop(0)
def is_empty(self): 判断是否为空 空返回 True 不为空 返回 False
return self.duilie == [ ]
def size(self): 查看长度
return len(self.duilie)
d=DuiLie( )
print(d.pop( ))
print(d.is_empty( ))
d.add(1)
d.add(2)
d.add(3)
print(d.pop( ))
print(d.is_empty( ))
输出结果: None
Ture
1
False
跳表:
查询O(logn),添加,删除O(logn)
一个每级跳过一定数量的数据的链表
散列表:
查询,删除,添加 O(1)
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。
散列表冲突解决:
- 开放寻址方式
- 拉链法
链接法其中优点有:
- 链接法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;
- 由于链接法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况。
开放寻址法不用指针,潜在地节约了空间,用这些空间可存放更多的槽,从而潜在地减少了冲突,提升了速度。
树:
数据结构–树