算法学习(Python版)

本文深入探讨了数据结构和算法中的关键概念,包括二分查找、选择排序、快速排序和合并排序。讲解了这些算法的工作原理、时间复杂度,并通过实例展示了它们的实现过程。此外,还提及了散列函数在数据存储和查找中的高效应用。
摘要由CSDN通过智能技术生成

Reference: 算法图解
git 代码

大O表示法

在这里插入图片描述

查找算法-二分查找

使用条件: 对于有序的数组
算法的时间: O ( l o g n ) O(log n) O(logn) 或者 l o g N + 1 logN + 1 logN+1次 [ 大O表示法说明了算法的增速 ]

import numpy as np
def binary_search( memory,desired_number):
    index_lower = 0
    index_upper = len(memory)-1

    index_chosen =  int ( (index_lower+index_upper)/2 )
    # python 3.6 中 不论类型 / 除法的结果都是 float型,但是List的index只能是整数,因此需要使用强制类型转换
    # index_chosen =  (index_lower+index_upper)//2   // 整数除法会考虑输入的类型,两个int类型结果会自动取整

    while index_lower<=index_upper:
        if memory[index_chosen] == desired_number:
            return index_chosen
        elif memory[index_chosen] < desired_number:
            index_lower = index_chosen+1
        else: 
            index_upper = index_chosen-1
        index_chosen =  int ( (index_upper+index_lower)/2 )
        # index_chosen = (index_upper+index_lower)//2
        
    return None 
    
""" test  """
memory = list( np.random.randint(100,size=30) )
memory.sort()
desired_number = np.random.randint(100,size=1)
print('memory: ',memory);
print('desired_number: ',desired_number)
print('index: ', binary_search(memory,desired_number) )

选择排序

数组是提前预留了固定数目的空间。如果我们对要存储的数据数量难以提前知道,那么就会造成 内存浪费(数组提前定义过大)或者在中途定义更大的数组,然后对数组数据全部进行转移的情况,浪费时间。因此对于数目未知的数据进行存储时,还是尽量选择可以柔性的链表。另外对于数据插入来说,链表可以通过修改地址的内容,实现链接的顺序改变。而对于数组,我们必须将数组的内容进行后移,才能实现数据的插入。

数组链表
读取O(1)O(n)
插入O(n)O(1)
删除O(n)O(1)

因此,对于随机读取次数较多的数据,我们还是最好使用数组;对于插入\删除比较多的情况,我们最好还是用链表。

选择排序通过每次选出数组中的最大元素,然后进行剔除;再选出剩余元素的最大元素,再进行剔除的方式进行 进行排序 O ( n 2 ) O(n^2) O(n2)

# 列表的删除命令  a.pop(index)  默认 a.pop()实现末尾元素的删除  
def search_small(array):  # 查找列表中最小元素以及对应的index
	array_small = array[0]
	array_small_index = 0
	
	for i in range(len(array)):
		if array[i] < array_small:
			array_small_index = i
			array_small = array[i]
	return [array_small,array_small_index]

def sort_ascend(array):
	array_sorted = []
	for i in range(len(array)):
		component,index = search_small(array)
		array_sorted.append(component) 
		array.pop(index)# 通过index剔除数组中的最小元素
	return array_sorted  
	
print( sort_ascend([2,1,5,7,9,3,3]) )

递归函数

递归包含基线条件和递归条件。 递归条件是函数调用自己的条件; 基线条件是函数不在调用自己的条件,避免形成无限循环

调用栈

栈: 后进先出。
我们可以将函数看作一个物体,调用函数的时候我们就会创建一个内存空间,用于存储函数中的的变量,通过内存空间中的变量去实现其他的语句。这个物体(内存空间)就压入栈中,在栈顶(表示正在执行的内容)。
那么当函数包含有其他函数的时候,就创建其他的内存空间生成该函数物体,然后将该物体压入栈中,此时该函数成为了栈顶。我们只有该函数内容都执行完,才能将该函数从栈中弹出(将该内存空间释放),然后执行之前的函数。
对于递归调用栈:
因为函数满足递归条件时,函数在一直递归,一直产生新的函数内存出现在栈顶,只有出现满足基线条件才会停止产生新的函数内存,然后才会将内存弹出,从而慢慢递归回去父函数。
这样的方式会占用很大的内存,因此不是所有的递归函数都可以实现。

分而治之

  1. 找到简单的基线条件;
  2. 将问题缩小规模(相同的问题,更小的规模),使其符合基线条件

快速排序

将N个数字的排序转化为1个数字在有序数组中的排序,同时采用递归思想。

def quick_sort(array):
	if len(array)>=2:
		last = array.pop()
		lower = []
		greater = []
		for component in array:
			if last<component:
				greater.append(component)
			else:
				lower.append(component)
		return quick_sort(lower) + [last] + quick_sort(greater)
		
	else:
		return array

print( quick_sort([2,4,3,7,1,0,-1,-5,-8,-11,-18,5]) )

合并排序

def MergeSort(array):
   if len(array)>=2:
   	array_front = MergeSort(array[:len(array)//2])
   	array_back = MergeSort(array[len(array)//2:])
   	
   	array_new = []
   	for i in range(len(array_front)):
   		for j in range(len(array_back)):
   			
   			if array_front[0]<=array_back[0]:
   				array_new.append(array_front[0])
   				array_front.pop(0)
   				break
   			else:
   				array_new.append(array_back[0])
   				array_back.pop(0)
   		if len(array_front)==0:
   			array_new = array_new + array_back
   			break
   		elif len(array_back) ==0:
   			array_new = array_new + array_front
   			break
   			
   	return array_new
   else:
   	return array
   	
print(MergeSort([2,4,3,7,1,0,-1,-5,-8,-11,-18,5]))

####################################################
###更好的写法
####################################################
def MergeSort(array):
   if len(array)>=2:
   	array_front = MergeSort(array[:len(array)//2])
   	array_back = MergeSort(array[len(array)//2:])
   	
   	array_new = []
   	while len(array_front)>0 and len(array_back)>0:
   			
   			if array_front[0]<=array_back[0]:
   				array_new.append(array_front[0])
   				array_front.pop(0)
   			else:
   				array_new.append(array_back[0])
   				array_back.pop(0)
   	array_new += array_front
   	array_new += array_back

   	return array_new
   else:
   	return array

   	
print(MergeSort([2,4,3,7,1,0,-1,-5,-8,-11,-18,5]))

冒泡排序

插入排序

散列函数

散列函数的特点:

  1. 散列函数将一个字符串(名称,key)对应到一个特定的内存地址,避免了数组中的查找等操作,一步到位。
  2. 散列函数实现了 固定字符串 会生成固定的内存地址;不同的字符串会生成不同的内存地址
  3. 散列函数根据字符串生成的内存地址是在可用范围以内的地址,不会超出范围。
    Python 中这样的散列函数 就是字典 dict。
voted = {}
value = voted.get("tom") # 如果"tom"在字典中,那就返回dict值; 如果"tom"不在字典中,那就返回None
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值