文章目录

  • ==排序算法=
  • 冒泡算法
  • 插入排序
  • 选择排序
  • 归并排序
  • 快速排序
  • 堆排序
  • 计数(桶)排序
  • 基数排序
  • ==查找算法==
  • 二分查找
  • 散列表查找(哈希表)
  • 树结构查找
  • 二叉树查找
  • 性质:
  • AVL查找
  • 红黑树查找
  • 字典树查找
  • ==搜索==
  • 深度优先遍历与着色
  • 广度优先遍历与着色
  • ==图非搜索==
  • 最小生成树
  • 最短路径
  • ==字符串算法==
  • 字符串排序算法
  • 单词查找算法
  • 子字符串查找算法
  • 正则表达算法
  • 数据压缩算法
  • ==基本算法思路==
  • 分而治之
  • 回溯算法
  • 动态规划
  • 贪心算法
  • 枚举算法
  • 递归
  • ==LRTCache==


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
参考字典树查找的实现方式

搜索

深度优先遍历与着色

广度优先遍历与着色

图非搜索

最小生成树

最短路径

字符串算法

字符串排序算法

单词查找算法

子字符串查找算法

正则表达算法

数据压缩算法

基本算法思路

分而治之

不断细分问题,把大问题分为两个小问题,在分为更小的问题

回溯算法

一旦发现当前步骤失败,回溯方法就返回上一个步骤,选择另外一种方式继续试错
多用在排列组合

动态规划

贪心算法

枚举算法

递归

LRTCache