算法的五大特性
- 输入: 算法具有0个或多个输入
- 输出: 算法至少有1个或多个输出
- 有穷性: 算法在有限的步骤之后会自动结束而不会无限循环,并且每一个步骤可以在可接受的时间内完成
- 确定性:算法中的每一步都有确定的含义,不会出现二义性
- 可行性:算法的每一步都是可行的,也就是说每一步都能
常见时间复杂度
O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n3) < O(2n) < O(n!) < O(2^ n)
因此,我们主要关注算法的最坏情况,亦即最坏时间复杂度。
Python内置类型性能分析
timeit模块可以用来测试一小段Python代码的执行速度。
Python列表创建的速度排序
list(range)
>[for i in range()]
>+
>append
数据结构
- 考虑数据究竟如何保存的问题,这就是数据结构。
- 抽象数据类型(ADT)的含义是指一个数学模型以及定义在此数学模型上的一组操作。即把数据类型和数据类型上的运算捆在一起,进行封装。
- 最常用的数据运算:插入、删除、修改、查找、排序
顺序表
顺序表,将元素顺序地存放在一块连续的存储区里,元素间的顺序关系由它们的存储顺序自然表示。
-
基本形式
- 图a:存储元素大小同一的数据,数据在物理地址内连续存储
- 图b:元素的大小不统一,顺序表存储元素的地址信息,实际元素另存,因为地址信息的大小统一。
-
顺序表结构
一个顺序表的完整信息包括两部分:1.表中的元素集合,2.为实现正确操作而需记录的信息,即有关表的整体情况的信息,这部分信息主要包括元素存储区的容量和当前表中已有的元素个数两项。 -
顺序表两种实现方式
- 元素存储区替换
- 一体式结构由于顺序表信息区与数据区连续存储在一起,所以若想更换数据区,则只能整体搬迁,即整个顺序表对象。
- 分离式结构若想更换数据区,只需将表信息区中的数据区链接地址更新即可,而该顺序表对象不变。
- 元素存储区扩充
- 采用分离式结构的顺序表,可以在不改变表对象的前提下对其数据存储区进行了扩充,所有使用这个表的地方都不必修改。只要程序的运行环境(计算机系统)还有空闲存储,这种表结构就不会因为满了而导致操作无法进行。人们把采用这种技术实现的顺序表称为动态顺序表,因为其容量可以在使用中动态变化。
- 扩充的两种策略
- 每次扩充增加固定数目的存储位置,如每次扩充增加10个元素位置,这种策略可称为线性增长。
特点:节省空间,但是扩充操作频繁,操作次数多。 - 每次扩充容量加倍,如每次扩充增加一倍存储空间。
特点:减少了扩充操作的执行次数,但可能会浪费空间资源。以空间换时间,推荐的方式。
- 每次扩充增加固定数目的存储位置,如每次扩充增加10个元素位置,这种策略可称为线性增长。
- Python中的顺序表
- Python中的list和tuple两种类型采用了顺序表的实现技术。tuple是不可变类型,即不变的顺序表,因此不支持改变其内部状态的任何操作,而其他方面,则与list的性质类似。
- 在Python的官方实现中,list就是一种采用分离式技术实现的动态顺序表。
链表
链表,将元素存放在通过链接构造起来的一系列存储块中。
- 单向链表
它的每个节点包含两个域,一个信息域(存储元素)和一个链接域(存储下个节点位置)。
需要一个头节点,将整个连边串联起来。
class SingleNode(object):
"""单链表节点"""
def __init__(self,item):
# _item存放数据元素
self.item = item
# _next下一个节点标识
self.next = None
class SingleLinkList(object):
def __init__(self):
self.__head = None
def is_empty(self):
'链表是否为空 '
return self.__head is None
def length(self):
'链表长度 '
cur = self.__head
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
'遍历整个链表'
cur = self.__head
while cur != None:
print(cur.item)
cur = cur.next
def add(self, item):
'链表头部添加元素'
node = Node(item)
node.next = self.__head
self.__head = node
def append(self, item):
'链表尾部添加元素'
if self.is_empty():
self.__head = Node(item)
else:
cur = self.__head
while cur.next != None:
cur = cur.next
cur.next = Node(item)
def insert(self, pos, item):
'指定位置添加元素'
if pos <= 0:
'元素添加至头部'
self.add(item)
elif pos >(self.length()-1):
'元素位置超过链表长度'
self.append(item)
else:
node = Node(item)
count = 0
pre = self.__head
while count < pos-1:
pre = pre.next
count += 1
node.next = pre.next
pre.next = node
def remove(self, item):
'删除节点 '
pre = None # 如果初始化pre=self.__head,第一个节点是要删除的节点无法判断
cur = self.__head
while cur != None:
if cur.item == item:
if not pre:
'第一个节点就是要删除的节点'
self.__head = cur.next
else:
pre.next = cur.next
break
else:
pre = cur
cur = cur.next
def search(self,item):
'查找节点是否存在 '
cur = self.__head
while cur != None:
if cur.item == item:
return True
cur = cur.next
return False
链表与顺序表的各种操作复杂度
链表的主要耗时操作是遍历查找,删除和插入操作本身的复杂度是O(1)。顺序表查找很快,主要耗时的操作是拷贝覆盖。
- 双向链表
class Node(object):
'双向链表节点'
def __init__(self,item):
self.item = item
self.next = None
self.prev = None
class DLinkList(object):
def __init__(self):
self.__head = None
def is_empty(self):
'链表是否为空 '
return self.__head is None
def length(self):
'链表长度 '
cur = self.__head
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
'遍历整个链表'
cur = self.__head
while cur != None:
print(cur.item)
cur = cur.next
def add(self, item):
'链表头部添加元素'
node = Node(item)
if self.is_empty():
self.__head =node
else:
node.next = self.__head
self.__head.prev = node
self.__head = node
def append(self, item):
'链表尾部添加元素'
node = Node(item)
if self.is_empty():
self.__head = node
else:
cur = self.__head
while cur.next != None:
cur = cur.next
node.prev = cur #节点的prev指向cur
cur.next = node #cur的next指向node
def insert(self, pos, item):
'指定位置添加元素'
if pos <= 0:
'元素添加至头部'
self.add(item)
elif pos >(self.length()-1):
'元素位置超过链表长度'
self.append(item)
else:
node = Node(item)
count = 0
cur = self.__head
while count < pos-1:
cur = cur.next
count += 1
node.prev = cur
node.next = cur.next
cur.next.prev = node
cur.next = node
def remove(self, item):
'删除节点 '
cur = self.__head
while cur != None:
if cur.item == item:
if cur == self.__head:
'第一个节点就是要删除的节点'
self.__head = cur.next
if cur.next != None:
cur.next.prev = None
else:
cur.prev.next = cur.next
if cur.next != None:
'如果删除的不是最后一个节点,将下个节点prev指向cur.prev'
cur.next.prev = cur.prev
break
else:
cur = cur.next
def search(self,item):
'查找节点是否存在 '
cur = self.__head
while cur != None:
if cur.item == item:
return True
cur = cur.next
return False
class Node(object):
'单循环链表节点'
def __init__(self,item):
self.item = item
self.next = None
class SCLinkList(object):
'单循环链表'
def __init__(self):
self.__head = None
def is_empty(self):
'链表是否为空 '
return self.__head is None
def length(self):
'链表长度 '
cur = self.__head
if self.is_empty:
return 0
count = 1
while cur.next != self.__head:
count += 1
cur = cur.next
return count
def travel(self):
'链表长度 '
cur = self.__head
if self.is_empty:
return 0
count = 1
while cur.next != self.__head:
count += 1
cur = cur.next
return count
def add(self, item):
'链表头部添加元素'
node = Node(item)
if self.is_empty():
self.__head = node
node.next = self.__head
else:
cur = self.__head
while cur.next != self.__head:
cur = cur.next
node.next = self.__head
self.__head = node
cur.next = self.__head
def append(self, item):
'链表尾部添加元素'
node = Node(item)
if self.is_empty():
self.__head = node
node.next = self.__head
else:
cur = self.__head
while cur.next != self.__head:
cur = cur.next
cur.next = node
node.next = self.__head
def insert(self, pos, item):
'指定位置添加元素'
if pos <= 0:
'元素添加至头部'
self.add(item)
elif pos >(self.length()-1):
'元素位置超过链表长度'
self.append(item)
else:
node = Node(item)
count = 0
cur = self.__head
while count < pos-1:
cur = cur.next
count += 1
node.next = cur.next
cur.next = node
def remove(self, item):
'删除节点 '
if self.is_empty():
'空链表'
return
pre = None
cur = self.__head
if cur.next == self.__head:
'只有一个节点'
if cur.item == item:
'第一个节点是删除节点'
self.__head = None
return
while cur.next != self.__head:
'两个及两个以上节点,不含尾节点'
if cur.item == item:
if not pre:
'第一个节点是删除节点'
while cur.next != self.__head:
'找到最后一个节点'
cur = cur.next
cur.next = self.__head.next
self.__head = self.__head.next
else:
pre.next = cur.next
return
else:
pre = cur
cur = cur.next
if cur.item == item:
'判断尾节点'
pre.next = self.__head
def search(self,item):
'查找节点是否存在 '
if self.is_empty():
'空表不存在任何值'
return False
cur = self.__head
if cur.item == item:
'判断头节点是否是存在的节点'
return True
while cur.next != self.__head:
cur = cur.next
if cur.item == item:
return True
return False