关于 数据结构 与算法的复杂度

程序=数据结构+算法(瑞士 尼克劳斯·威茨 提出)
数据结构:逻辑结构 和 物理结构
逻辑结构:集合结构、线性结构、树形结构、图形结构
物理结构:数据存储
数据元素的存储结构:顺序存储结构(地址连续的存储单元) 和 链式存储结构(任意存储单元,数据间使用指针关联)

算法的基本特性:

  1. 输入性 有零个或多个输入
  2. 输出性 至少有一个或多个输出
  3. 有穷性 算法在执行有限步后能自动结束,不会出现无限循环
  4. 确定性 算法的每一步都具有确定的含义,不会出现二义性
  5. 可行性 算法的每一步都能够通过执行有限操作完成

算法的复杂度: 时间复杂度(计算的时间) 和 空间复杂度(需要的内存空间)
度量时间复杂度: 大O表示法 O( ) 度量一个算法好坏的重要指标
时间复杂度基本计算规则:

  1. 基本操作,即只有常数项,时间复杂度为 O(1)
  2. 顺序结构,时间复杂度 按 加法计算
  3. 循环结构,时间复杂度 按 乘法计算
  4. 分支结构,时间复杂度取最大值 (if—elif—else)
  5. 判断一个算法的效率时,往往只需要关注 操作数量的最高次项,其他 次要项 和 常数项可以忽略
  6. 在没有特殊说明时,分析算法的时间复杂度 都是指 最坏时间复杂度

所消耗的时间从小到大:
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)

​数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量,它可以存储一个固定大小的相同类型元素的顺序集合。

线性表:有限序列

线性表的基本特征:

  1. 第一个数据元素 没有前驱元素
  2. 最后一个数据元素 没有后继元素
  3. 其余每个数据元素 只有一个前驱元素和一个后继元素

线性表按物理存储结构顺序表(顺序存储) 和 链表(链式存储)
顺序表的优缺点:

  1. 优点:支持随机访问
  2. 缺点:插入和删除操作需要移动大量的元素,造成存储空间的碎片

链表:合理运用空间
链表的查询效率O(n),删除效率,添加效率O(1)

  1. 单向链表:每个节点包含两个域,一个元素域 和 一个链接域(指向下一节点),最后一个节点的链接域为 None
  2. 单向循环链表:在单链表的基础上,最后一个节点的链接域 不为 None ,而是指向连接表的头节点
  3. 双向链接表:每个节点包含三个域,一个元素域 和 两个链接域 ,两个链接域 分别指向上一节点、下一节点,第一个节点 连前面节点的链接域写 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)而直接进行访问的数据结构。

散列表冲突解决:

  • 开放寻址方式
  • 拉链法

链接法其中优点有:

  1. 链接法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;
  2. 由于链接法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况。

开放寻址法不用指针,潜在地节约了空间,用这些空间可存放更多的槽,从而潜在地减少了冲突,提升了速度。

树:

数据结构–树

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页