## Python中变量标识的本质
> python中的变量名不保存值,保存值的地址。
> 变量等于谁即相当于该变量指向那个ji'e点
## Python中变量标识的本质
> python中的变量名不保存值,保存值的地址。
> 变量等于谁即相当于该变量指向那个ji'e点
## 单向链表
### 定义:
> 单链表是链表中最简单的一种形式,它的节点包含两个域,一个信息域和一个链接域。这个链接指向链表中的下一个节点。而最后一个节点的链接域则指向一个空值。
- 表元素域用来存放具体数据
- 链接域用来存放下一个节点的位置
- 变量p指向链表的头节点的位置,从p出发能找到表中的任意节点。
#链表
> 线性表:链表和顺序表的统称,一个线性表是某类元素的一个集合,还记录这元素之间的一种顺序关系。最基本的数据结构之一。
## 为什么要使用链表
> 链表可以充分利用计算机内存空间,实现灵活的内存动态管理。
## 链表的定义
> 链表是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样连续存储数据,而是在每一个节点(数据存储单元)里存放下一个节点的位置信息(即地址)。
### 链表的节点
一个节点由两部分组成,数据区和链接区。第一部分保存数据信息,第二部分保存下一个节点的数据信息地址。
### 顺序表删除元素
- 删除尾部元素 O(1)
- 非保序的元素插入 O(1)
- 保序的元素插入 O(N)
> 元素的删除与增加从尾部删除或添加比从头部或中间删除或添加要简单许多。时间复杂度低。
### Python中的顺序表
Python和中的list和tuple就是采用了顺序表的实现技术。
### list的基本实现技术
主要特征:
- 基于下标位置的高效元素访问和更新,复杂度为O(1)
- 允许任意加入元素,且在不断加入元素过程中,表对象的标识(id)不变。为满足该特征,就必须能更换元素存储区,并且为保证更换存储区时list对象的标识id不变,只能采用分离式实现技术
> list就是一种采用分离式技术实现的动态顺序表。这就是为什么append比在指定位置插入元素效率高的原因。
> 支持扩充的顺序表称为动态顺序表。
在python的官方实现中,list采用了如下的策略:在建立空表时,系统分配一块能容纳八个元素的存储区;在执行插入操作时,如果元素存储区满就换一块四倍大的存储区。但如果此时的表已经很大,则改变策略,采用加一倍的方法。引入这种改变策略的方式,是为了避免出现过多空闲的存储位置。
### 顺序表数据区的替换与扩充
> 扩充的两种策略:
- 每次扩充增加固定数目的存储位置。线性增长。特点:节省空间,操作频繁,操作次数多
- 每次扩充容量加倍
特点:减少了扩充操作的执行次数,但可能会浪费空间资源。以空间换时间,推荐的方式
### 顺序表的结构与实现
> 顺序表的结构:
- 数据区:元素集合
- 表头信息:为实现正确操作而需记录的信息:主要包括存储区的容量和当前表中已有的元素个数亮相。
### 顺序表的两种基本实现方式
- 一体式结构:将表头和数据区以连续的方式存储在一块存储区里
- 分离式结构:表对象里只保存与整个表有关的信息,实际元素存放在另一个独立的元素储存区里,通过连接与基本表相关联。==在链接中存储元素储存区的地址。
> 优劣分析:采用分离式需要额外进行一次间接访问。但是当元素个数超出储存区容量时,需要创建一个新的元素储存区,一体式结构需要表头信息同样复制到新的元素储存区中,而分离式结构只需更改链接处的地址。在分离式结构中,表头的起始地址是不改变的。一般选用分离式结构顺序表。
### 内存的本质
## 顺序表
int=1,2,3,4,5
内存是以一个字节作为基本单元,一个字节有八位,内存是一个连续的存储空间。
cpu通过查询内存地址来提取内存中存储的内容。
一个字节的八位整体会有一个地址。
整型会占四个字节。一个整型会有32位,占四个字节。
> 取整型和取字符的方法不同。
### 顺序表的基本布局
## 数据结构引入
> 数据结构指数据对象中数据元素之间的关系。数据结构就是对基本类型的封装
> 列表、元组、字典。需要自己去定义数据结构,不一样的数据结构的时间复杂度是不一样的。
==算法与数据结构的区别:
数据结构只是静态的描述了数据元素之间的关系
> 程序=数据机构+算法
> 总结:算法是为了解决实际问题而设计的,数据结构是算法需要处理的问题载体。
## 抽象数据类型
> 抽象数据类型(ADT)的含义是指一个数学模型以及定义在次数学模型上的一组操作,即把数据类型和数据类型上的运算捆在一起,进行封装。
> 常用的数据运算有五种:
- 插入
- 删除
- 修改
- 查找
- 排序
## Python 内置类型性能分析
> 列表添加
- list.append()
- list.insert()
### timeit模块
> 用来测试一小段python代码的执行速度
class timeit.Timer(stmt="pass",setup="pass",timer=<timer function>)
- Timer 是测量小段代码执行速度的类
- stmt参数时要测试的代码语句
- setup参数是代码运行时需要的设置
- timer参数是一个定时器函数,与平台有关。
>time.Timer.timeit(number=1000000)
number参数是测试代码时的测试次数,默认为1000000次。方法返回执行代码的平均耗时,一个float类型的秒数。
### list测试操作
## 常见的时间复杂度
### 最坏时间复杂度
> 同样的算法对于处理数据的不同也会复杂度也会不同。
- 算法完成工作最少需要多少基本操作,即最优时间复杂度
- 算法完成工作最多需要多少基本操作,即最坏时间复杂度
- 算法完成工作平均需要多少基本操作,即平均时间复杂度。
主要关注最坏时间复杂度,是一种保证,表明算法在此种程度的基本操作中一定能完成工作。
### 时间复杂度的几条基本计算原则
- 基本操作,即只有常数项,认为其时间复杂度未O(1)
- 顺序结构,按加法计算
- 循环结构:按乘法计算
- 分支结构:时间复杂度取最大值
- 判断一个算法效率时,往往只需要关注最高次项,,其他次项和常数项基本可以忽略。
- 我们所分析的算法的时间复杂度都是指最坏时间复杂度。
> 对于第二次改进的时间复杂度的分析 T(n)=n^2 *(1+max(0,1))=n^2+2=O(n^2)
## 算法效率衡量
### 执行时间反应算法效率
> 实现算法程序的执行时间可以反映出算法的效率,即算法的优劣
> 单纯依靠运行的时间来比较算法的优劣并不一定是客观准确的。
### 时间复杂度与”大O计法“
> 每台机器执行的总时间不同,但是执行基本运算数量大体相同。
> 时间复杂度:描述时间上的效率问题, 经历了多少基本运算步骤。T(n)
- 第一次尝试运算步骤:1000*1000*1000*2
T(n)=N^3 * 2, N代表了问题的规模
T(n)=N^ * k+c, 可以理解为两个T属于一个量级
> 渐近函数:g(n)=N^3, 可以理解为g函数时T函数的渐近函数。g(n)称为一个时间复杂度的大O计法。
# 数据结构与算法(Python)
## 引入
> 枚举法:如果a+b+c=1000,a**2+b**2=c**2, 如何求出所有的abc的可能。
### 算法的概念
> ==算法是计算机处理信息的本质==,因为计算机程序本质上是一个算法来告诉计算机确切的步骤来执行一个指定的任务。一般地,当算法在处理信息时,会从输入设备或数据的存储地址读取数据,把结果写入输入设备或者某个存储地址供以后再调用
> 算法是独立存在的==一种解决问题的方法和思想==。
### 算法的五大特性
- 输入:算法具有0个或多个输入
- 输出:算法至少有一个或多个输出
- 有穷性:算法在有限的步骤之后会自动结束而不会无限循环,并且每一个步骤可以在可接受的时间内完成
- 确定性:算法中的每一步都有确定的含义,不会出现二义性:看到这种思路就知道要做什么
- 可行性:算法的每一步都是可行的,也就是说每一步都能够执行有限的次数完:ke'yu'ying'y