文章目录
import cProfile
def main():
time.sleep(0.1)
# cProfile.run("main()")
测试函数运行的速度
==排序算法=
冒泡算法
遍历数组,第一个数一次跟后面的数对比,如果比后面的大就交换。以此类推 O(n^2)
def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(0,n-i-1):
if arr[j] > arr[j+1] :
arr[j],arr[j+1] = arr[j+1],arr[j]
return arr
插入排序
遍历列表,取出第一个数据。然后进行比较,找到合适的位置插入 O(n^2)
def insertion_sort(arr):
n = len(arr)
for i in range(1,n):
key = arr[i]
j = i-1
while j>=0 and key < arr[j]:
arr[j+1] = arr[j]
j -= 1
arr[j+1] = key
return arr
选择排序
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕 O(n^2)
def select_sort(arr):
n = len(arr)
min_idx = i
for i in range(n):
for j in range(i+1,n):
if arr[min_idx] >arr[i]:
min_idx = i
arr[i],arr[min_idx] = arr[min_idx],arr[i]
return arr
归并排序
一直将数组拆分,分到只有两个或者一个,然后比较大小,接着对拆分的数组逐一进行比较合并 O(nlogn)
def merge(arr,l,m,r):
n1 = m-l+1
n2 = r-m
# 建立空数组,存放并分的数组
L = [0]*n1
R = [0]*n2
# 将数据copy到临时数组里
for i in range(n1):
L[i] = arr[l+i]
for j in range(n2):
R[j] = arr[m+1+j]
i = 0
j = 0
k = l
# 将临时数组的数据比较重新按大小归入原数组
while i < n1 and j < n2:
if L[i] > R[j] :
arr[k] = R[j]
j += 1
else :
arr[k] = L[i]
i += 1
k += 1
while i < n1 :
arr[k] = L[i]
i += 1
k += 1
while j < n2 :
arr[k] = R[j]
j += 1
k += 1
def merge_sort(arr,l,r):
# l是起始下标,r是结束下标
if l < r:
m = int((l+(r-1))/2)
mergeSort(arr, l, m)
mergeSort(arr, m+1, r)
merge(arr, l, m, r)
快速排序
# 判断数组的第一索引是否小于最后一个索引
# 选中第一个数字
# 遍历后面的数字,若后面的数字比第一个数字小,交换选中的顺位位置
# 交换第一个数字与最后顺位交换的数字
# 在交换位置将数组分成两部分,执行第一步 O(nlogn)
def quick_sort(arr,l,h) :
'''
:param arr: 数组
:param l: 起始索引
:param h: 结束索引
:return:
'''
if l < h:
f = arr[l]
k = l
for i in range(l,h+1):
if arr[i]< f:
k +=1
arr[k],arr[i] = arr[i],arr[k]
arr[l],arr[k] = arr[k],arr[l]
quick_sort(arr,l,k)
quick_sort(arr,k+1,h)
堆排序
堆是完全二叉树
数组的堆结构描述
父节点i的左子节点在位置(2i+1)
父节点i的右子节点在位置(2i+2)
子节点i的父节点在位置(i-1)//2 O(nlogn)
# 循环列表长度-1,记作交换次数
# 遍历列表,使得子节点与父节点进行比较,若大于父节点交换
# 将0节点与最后子节点交换
def heap_sort(arr):
n = len(arr)
for i in range(n-1):
for j in range(n-1-i,0,-1):
if arr[j]>arr[(j-1)//2]:
arr[(j-1)//2],arr[j] = arr[j],arr[(j-1)//2]
arr[0],arr[n-1-i] = arr[n-1-i],arr[0]
计数(桶)排序
创建一个序列,里面包含待排序列表中最大的元素
遍历列表,每一个值然后在对应的序列上加一
在遍历序列,把序列号按照对应数字的多少归到原列表中 O(n+k)
def bucket_sort(arr):
max_size = max(arr)
bucket_list = [0 for i in range(max_size+1)]
for i in arr:
bucket_list[i] +=1
j = 0
for i in range(len(bucket_list)):
if bucket_list[i] > 0:
arr[j:j+bucket_list[i]] = [i]*bucket_list[i]
j += bucket_list[i]
print(arr)
基数排序
基数排序跟桶(计数)排序一样,是其的升级版本。
首先对数列按个位数大小重新排序,然后在进行十位数的大小排序,以此类推。O(n+k)
def radix_sort(arr,n):
'''
arr:排序数组
n:数组中最大数的位数
'''
for k in range(n): #n轮排序
s=[[] for i in range(10)]
for i in arr:
s[i/(10**k)%10].append(i)
A=[a for b in s for a in b]
return arr
查找算法
二分查找
有序的数组,进行对x(目标查找元素)查找,返回x在数组的位置
每次查找一半数据,找到就返回,找不到就继续下一半。
# 返回 x 在 arr 中的索引,如果不存在返回 -1
def binary_search (arr, l, r, x):
'''
l: 数组起始索引
r: 数组结束索引
'''
# 基本判断
if r >= l:
mid = int(l + (r - l)/2)
# 元素整好的中间位置
if arr[mid] == x:
return mid
# 元素小于中间位置的元素,只需要再比较左边的元素
elif arr[mid] > x:
return binary_search(arr, l, mid-1, x)
# 元素大于中间位置的元素,只需要再比较右边的元素
else:
return binary_search(arr, mid+1, r, x)
else:
# 不存在
return -1
散列表查找(哈希表)
树结构查找
-
二叉树查找
首先说一下二叉树结构:
二叉树是每个节点最多有两个子树的树结构
没有父节点的节点称为根节点
每一个非根节点有且只有一个父节点性质:
二叉树第i层上的结点数目最多为 2{i-1} (i≥1)。 深度为k的二叉树至多有2{k}-1个结点(k≥1)。 包含n个结点的二叉树的高度至少为log2 (n+1)。 在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1。
Python实现数据结构将会在数据结构中展示
二叉树的查找:假设此时从节点node开始查找某值,此时要遍历二叉树的所有节点,直到找到该节点,就停止返回true,如果二叉树遍历完了还没有找到就返回false。创建一个二叉树结构类 class Node (): def __inie__(self,x): self.value = x self.left = None self.right = None # 普通二叉树查找 def get(x,data): if x == None: return False if x.data == data: return True flag1 = False flag2 = False flag1 = get(x.left, data) flag2 = get(x.right, data) return flag1|flag2
二叉排序树查找
利用二叉排序树的性质:节点的左子树都是小于这个节点,节点的右子树都是大于这个节点的。
节点node开始查找,如果在要找的值小于这个节点的值,就在左子树中查找,如果要找的值大于这个节点的值,就在该节点的右子树中查找,一直找到某一个叶子节点,还没有找到,就返回false。def get(x,data): if x == None: return False if data < x.data: return get(x.left,data) elif data < x.data: return get(x.right,data) else:return True
-
AVL查找
AVL的查找过程同二叉排序树查找,只不过AVL树的结构不同于二叉排序树。AVL是平衡树
-
红黑树查找
查找过程同二叉树,重要的是二叉树的实现和数据操作
-
字典树查找
字典树是哈希树的一种,字典树可以理解为二叉树种的父为key,子为value
参考字典树查找的实现方式
搜索
深度优先遍历与着色
广度优先遍历与着色
图非搜索
最小生成树
最短路径
字符串算法
字符串排序算法
单词查找算法
子字符串查找算法
正则表达算法
数据压缩算法
基本算法思路
分而治之
不断细分问题,把大问题分为两个小问题,在分为更小的问题
回溯算法
一旦发现当前步骤失败,回溯方法就返回上一个步骤,选择另外一种方式继续试错
多用在排列组合