python数据结构及算法
一. 数据结构与算法
1. 算法的概念:算法是独立存在的一种解决问题的方法和思想
2. 算法的特征:输入,输出,有穷性,确定性,可行性
3. 时间复杂度是实现算法程序所需要的时间,即算法的优劣
4. 数据结构是指数据对象中数据元素之间的关系
5. 程序 = 数据结构 + 算法
6. 算法是为了解决实际问题而设计的,数据结构是算法需要处理的问题载体
二. 顺序表
1. 顺序表:将元素顺序地存放在一块连续的存储区里,元素间的顺序关系由它们的存储顺序自然表示
2. 元素的物理地址 = 首地址 + 元素下标 * 存储单元大小
3. 顺序表分为一体式结构和分离式结构
4. 元素存储区替换:一体式结构需要移动整个数据区;分离式结构只需要移动数据区域链接地址即可
三. 链表
1. 将元素存放在通过链接构造起来的一系列存储块中,在每个结点存放下一个结点的地址
2. 单链表:单链表包含两个域,一个信息域,一个链接域(指向下一个节点)
3. 信息域存放具体的数据,链接域存放下一个结点的地址
4. 单链表操作:
操作 | 功能 |
is_empty | 链表是否为空 |
length() | 链表长度 |
travel() | 遍历整个链表 |
add(item) | 链表头部添加元素 |
qppend(item) | 链表尾部添加元素 |
insert(位置,item) | 指定位置添加元素 |
remove(item) | 删除节点 |
search()item | *查找节点是否存在 |
5. 单向循环链表:在单链表的尾部增加了一个指向头结点的链接
6. 双向链表:每个节点都包括一个数据域和两个链接域(一个指向前驱节点,一个指向后继节点)
四. 栈
1. 特点:只允许在容器的一端进行加入数据和输出数据(后进先出)
2. 栈的操作:
操作 | 功能 |
stack() | 创建一个新的空栈 |
push(item) | 添加一个新的元素item到栈顶 |
pop() | 弹出栈顶元素 |
peek() | 返回栈顶元素 |
is_empty | 判断栈是否为空 |
size() | 返回栈的元素个数 |
五. 队列
1. 队列是只允许在一端进行插入操作,在另一端进行删除操作的线性表(先进先出)
2. 双端队列:可以在任意一端入队和出队
3. 队列操作:
操作 | 功能 |
Deque() | 创建一个空的双端队列 |
add_from(item) | 在队头加入一个item元素 |
add_rear(item) | 在队尾加入一个item元素 |
remove_rear() | 在队尾删除一个item元素 |
is_empty | 判断双端队列是否为空 |
size() | 返回队列大小 |
六. 排序与搜索
排序算法是一种能将一串数字依照特定的顺序排列的一种算法
1. 冒泡排序
方法:把数组从前往后,两两比较,较大的数放在最后一位;每轮得到一个最大值且不参与下一轮排序,直到所有数字排序完毕
稳定性:稳定
代码如下:
def bubble_sort(alist):
"""冒泡排序"""
n = len(alist)
for j in range(n-1):
count = 0
for i in range(0,n-1):
"""序列从头走到尾"""
if alist[i] > alist[i+1]:
alist[i],alist[i+1] = alist[i+1],alist[i]
count += 1
if 0 == count:
return
2. 选择排序
方法:每一轮找出一个最小值与第一个数交换,第二轮在除了第一个数外其余数里找一个最小的与第二个数交换,依此类推
稳定性:不稳定
代码如下:
def select_sort(alist):
"""选择排序"""
n = len(alist)
for j in range(n-1):
min_index = j
for i in range(j,n):
if alist[min_index] > alist[i]:
min_index = i
alist[j],alist[min_index] = alist[min_index],alist[j]
3. 插入排序
方法:第一轮在前两个数种寻找最小值插入到第一个数,第二轮从前三个数里找最小值插入到第一个数,依此类推
稳定性:稳定
代码如下:
def insert_sort(alist):
"""插入排序"""
n = len(alist)
for j in range(1,n):
i = j
while i > 0:
if alist[i] < alist[i-1]:
alist[i],alist[i-1] = alist[i-1],alist[i]
i -= 1
else:
break
4. 快速排序
方法:首先,把第一个数设置为基数,使用high和low下标,low在头(但不指向基数),high在尾,向中间移动,移动规则为low向后移动,遇到比基数大的停止,high遇到比基数小的停止,当high和low都停止时,二者交换,继续往中间移动,直到二者重合,把基数插入到重合点前;第二轮把数列以基数为中心分为两部分,继续进行相同操作
稳定性:不稳定
代码如下:
def quick_sort(alist,first,last):
"""快速排序"""
if first >= last:
return
mid_value = alist[first]
low = first
high = last
while low < high:
while low < high and alist[high] >= mid_value:
high -= 1
alist[low] = alist[high]
while low < high and alist[low] < mid_value:
low += 1
alist[high] = alist[low]
alist[low] = mid_value
quick_sort(alist,first,low-1)
quick_sort(alist,low+1,last)
5. 希尔排序
方法:第一轮将数列分为以n//2为一组,每部分的对应位置进行插入排序;第二轮分为n//2//2部分,继续进行相同操作,直到分成n部分
稳定性:不稳定
代码如下:
def shell_sort(alist):
"""希尔排序"""
n = len(alist)
gap = n//2
while gap > 0:
for j in range(gap,n):
i=j
while i>0:
if alist[i] < alist[i-gap]:
alist[i],alist[i-gap] = alist[i-gap],alist[i]
i -= gap
else:
break
gap //= 2
6. 归并排序
方法:把数组先分为n/2为一组,再分为n/2/2为一组,直到n/n为一组,再把数字两两合并,第一次合并时,合并成2个为一组,根据左下标和右下标比较,较小的数先输出,直到一组数据为空,另一组数直接插入,第二次合并时,合并成4个为一组,直到一组数为空
稳定性:稳定
代码如下:
def merge_sort(alist):
"""归并排序"""
n = len(alist)
if n<=1:
return alist
mid=n//2
left_li=merge_sort(alist[:mid])
right_li=merge_sort(alist[mid:])
left_pointer,right_pointer=0,0
result=[]
while left_pointer < len(left_li) and right_pointer < len(right_li):
if left_li[left_pointer] < right_li[right_pointer]:
result.append(left_li[left_pointer])
left_pointer+=1
else:
result.append(right_li[right_pointer])
right_pointer+=1
result+=left_li[left_pointer:]
result+=right_li[right_pointer:]
return result
7. 搜索
二分查找也叫折半查找,只能作用到顺序表
特点:比较次数少,速度快
七. 树与树算法
度:一个节点含有的子树的个数
树的度:最大的节点含有的子树的个数
节点的层次:从根开始定义,根为第一层,跟的子节点为第二层,依此类推
有序树分为:二叉树,霍夫曼树,B树
1. 二叉树
分类:二叉树分为完全二叉树,满二叉树,平衡二叉树(子树层次相差不大于1),排序二叉树(左小右大)
性质:在二叉树的第i层上至多有2^(i-1)个节点;
深度为k的二叉树至多有2^k-1个节点;
对于任意一颗二叉树,如果其叶子节点数为NO,而度数为2的节点总数为N2,则NO=N2+1;
具有n个节点的完全二叉树的深度为log2(n+1)
2. 树的遍历
分类:先序遍历;中序遍历;后序遍历
先序遍历先遍历根节点,再遍历左子树,再遍历右子树
中序遍历先遍历左子树,再遍历根节点,再遍历右子树
后序遍历先遍历左子树,再遍历右子树,再遍历根节点