数据结构与算法学习之路

“算法和数据结构可以认为是绝对代码能力和耐心努力的一种证明”

一、python

2021【7.19】菜鸟教程数据类型
【8.10】list和数组的区别
10.28 通过变量名[索引值 : 索引值 : 步长] ———— 进行切片
11.7 List数据前面加‘*’表示将List拆分为独立的参数
11.12 list[左闭,右开] 与n=len(list)+1结合
【8.20】集合
【8.23】迭代器与生成器
【10.5】enumerate
【10.28】类
【10.30】字典
【2.10】易化AI
类:
动态的属性,静态的方法
self就是p,指向对象

class Person:     #//定义类(只是想法)
  name = 'lili'   #//类属性
  def talk(self): #//类行为(方法):形参self必须有,代表类的实例
    print("can talk,my name is:",self.name);

p = Person()      #//新建类的实例对象
p.talk()          #//调用对象的方法(无参,但其实有参,它是隐藏的第一个实参,为类的实例)
print("name is",p.name)  #//访问对象的属性	
p.age=30          #//可动态添加(python是动态语言)
print("new age is",p.age)

函数做参数:

def fn(callback): #//函数参数: ()  --  输入(做事需要什么东西, 如 callback) 
  print(callback,' type:',type(callback));
  callback();    #//通过参数,间接调用函数 (回调函数)       

def start():
  print('start tv');

fn(start);  #//函数做参数传入

【2.11】
类对象做函数参数

class Animal:  #//定义一个类 Animal
  name = "animal";
  def breath(this):
    print("can breath from water");

def air():
  print("breath from air");
def change(o):
  print("after change");
  o.breath = air;  //将air函数赋给传进来的类的breath方法

obj =  Animal(); #//新建对象实例
print(obj.name);
obj.breath();
change(obj);     #//对象做实参(引用类型传递 是地址传递,指向的是同一实体)
print(obj.name);
obj.breath();	

函数的不定参数
*args 传入的参数是 元组类型

def test(*args):    
    print(args)   
    for i in args:
        print(i)

test(1,2,3)

**kwargs 传入的参数是 dict 类型

def test(**kwargs):
    print(kwargs)
    keys = kwargs.keys()
    value = kwargs.values()
    print(keys)
    print(value)

test(a=1,b=2,c=3,d=4)

【2.12】函数式编程:
尽量的少使用循环,忽略循环的影响
把重要的部分提取出来,修改函数代码即可
计算列表倍数

①以往编程
data = [ 1, 2, 3, 4, 5, 6]
res1 =[ ]
for n in data:
res1.append ( n * 2)
print (res1)

②列表解析式
res2 -[ n*2 for n in data ]

③函数式编程
def doubled(n) :
return n * 2
map ( doubled, data)

①匿名函数
把定义和调用放在一起

(lambda  输入n:表达式n×2([ 1, 2, 3, 4, 5, 6])

②闭包
如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包
在网页注册账号时会应用到,填错时保留之前信息。

def outer(x):
    def inner(y):  #//inner是闭包,它引用外部的变量x
        return x + y
    return inner 
    
a = outer(2)
print('result:',a(3)) #//驻留了前面2的信息

因为X是基础变量类型int,不能更改外部变量
将其改为列表或者字典就可以更改X信息
【2.13】
封装、继承
多重继承 尽量少使用,因为使得son与father,mother绑定在一起,增加了耦合性

class Father:
  name ="father";
  def football(self):
    print(self.name,"play football good");
  def talk(self):
    print(self.name, "talk fast");

class Mother:
  name ="mother"
  def music(self):
    print(self.name,"play music good");
  def talk(self):
    print(self.name, "talk slow");

class Son(Father,Mother): #//多重继承:儿子同时继承父母天赋
  name ="son"
  def draw(self):
    print(self.name,"draw good");

s =Son();
s.football();
s.music()
s.draw()
s.talk()  #talk fast//python没有二义性问题(c++有),父母都有时,以前一个为准

python 天生多态(动态语言,运行时动态绑定,边解析边执行),c++为静态语言
构造函数__init__
析构函数 销毁所创建的函数,释放资源

class Line:
  name='a line'
  def __init__(this,len=3): #//可选,无时,会有默认的
    this.length = len
    print('构造函数运行')
  def __del__(this): #//可选,无时,会有默认的
    print('析构函数运行,释放资源')
  def show(this):
    print('length is',this.length);

obj = Line() #//创建对象实例时,自动调用构造函数。
obj.show();  #//执行完自动析构(引用计数方式,进行垃圾回收)

【2.14】
函数的权限
在属性和方法前加下划线会限制其外部访问

class Girl:      #//定义类(只是想法)
  name = 'girl'
  __age = 30     #//私有属性(以下划线开头)
  def registerInfo(this):
    print(this.name,'age is ',this.__age)  #//私有属性仅内部能访问
  def __getAge(this): #//私有方法(以下划线开头)
    print('private __getAge is ',this.__age)

g = Girl()
g.registerInfo()
print(g.name)
g.__getAge()        #//报错: 私有方法外部不能访问 
print(g.__age)      #//报错: 私有属性外部不能访问   (女孩年龄是秘密)        
print(g._Girl__age) #//通过这种方式,外面也能够访问“私有”变量;调试中是比较有用的!

链式调用

class Person:
  def name(self, str):
    self.name = str
    return self
  def age(self, str):
    self.age = str
    return self
  def show(self):
    return self.name,self.age

obj=Person()
print(obj.name("ivan").age(37).show())

实际应用:用链式调用,实现多关键词的信息查询过滤

class Query():
    def __init__(self):
        self.query_condition = {}
    def filter(self, **kwargs):
        self.query_condition.update(kwargs)
        return self
				
query = Query()
a = query.filter(name='lili').filter(age__gt=18, address='chengdu').filter(salary=12000)
print(query.query_condition) #//最后提交给数据库的查询信息

多线程
socket通信:
在这里插入图片描述
在python中调用C

#include <stdio.h>

int add_int(int, int);
int add_int(int num1, int num2){
  printf("add num1+num2\n");
  return num1 + num2;
}

使用命令gcc -shared -Wl,-soname,adder -o adder.so -fPIC add.c //在Linux编译生成动态库

//use.py
from ctypes import *

adder = CDLL('./adder.so') #//load c share lib
print(adder.add_int(4,5))

【2023.2.24】近几日开始准备实习的知识盲点
1.==和is区别
" is" (同一性运算符)是用来比较 a 和 b 是不是指向同一个内存单元,而"=="是用来比较 a 和 b指向的内存单元中的值是不是相等。
在这里插入图片描述
在这里插入图片描述
其实这是python解释器搞得鬼,具体是因为python的垃圾回收机制,这个垃圾回收机制会在之后的文章中详细介绍,至于出现上面这种现象是因为一个叫小整数对象池的东西,python为了优化速度,会把【-5,256】之间的数据提前存放在小整数对象池中,程序中只要用的【-5,256】之间的数据不会再重新创建一份,都是指向对象池中的同一份数据

2.引用、浅拷贝、深拷贝
①引用
a=[1,2,3]
b=a
改变b时a同时改变,是因为b和a是同一个地址
如何改变这种现象?就涉及到了拷贝技术
②浅拷贝
b=a.copy()
b=a[:]
以上两种方式改变b时不会改变a;
但是出现a是双层列表时就不行了,这时候使用深拷贝可以解决
③深拷贝
b=copy.copy(a)
3.函数有默认返回值None
4.可解析的数据类型
【2023.3.13】正则表达式
(1)限定符
?代表前面的字符可以出现0或者1次
*代表前面的字符可以出现0或者n次
+代表前面的字符必须出现1次以上
{}指定前面字符出现的次数,也可以是一个范围{1,n},后面的n也可以省略
()可以将多个字符括起来一起限定
(2)或运算符
a (cat|dog) 代表先匹配a 然后要么是cat出现要么是dog出现
(3)字符类
[abc]代表要求匹配的字符只能取自[]内
[ ^ 0-9]代表除了0-9之外的字符
(4)元字符
\b匹配一个隐式位置(字符与字符之间的位置)
\d 代表数字字符 = [0-9]
\w代表单词字符 =所有的Unicode单词字符,包含下划线和中文字符
\s代表空白字符,包含tab和换行符
\D代表非数字字符
\W代表非单词字符
.代表任意字符但是不包括换行符
^只会匹配行首 $只会匹配行尾
高级概念
贪婪(匹配结果尽可能多)和懒惰(匹配结果尽可能少)匹配
在这里插入图片描述
【3.13】不可变数据类型和可变数据类型
概念:指改变变量内容时,地址发没发生改变
不可变数据类型(当该数据类型的对应变量的值发生了改变,那么它对应的内存地址也会发生改变,就称不可变数据类型):整形、字符串、元组
可变数据类型:集合、字典、列表
【4.13】
装饰器:
函数的前提知识:
可以调用函数
可以将函数赋值给其它变量
可以把它当成参数传给其它函数
可以在函数内定义一个函数,并做为返回值返回

装饰器就是在不影响原函数功能的情况下 给它添加一些功能(这个功能会被很多函数用到)。

"""
写两个不同语言说你好的函数,并且第一句是中文的欢迎!
"""
####第一个版本
def fun1(message :str):
	print("你好!")
	print("Hello "+message)

def fun2(message :str):
	print("你好!")
	print("Ciao "+message)
	
fun1("volcano")#output:你好! Hello volcano

#我们会发现以上两个函数都需要做重复的第一步,因此用Decorator来解决这一问题
####第二个版本
def my_decorator(func):#定义一个装饰器 传入函数名
	def wapper(s): #装饰器的重复功能函数
		print("你好!")
		return func(s)#返回传入函数的执行结果
	return wapper  #返回wapper函数

def fun1(message :str):
	print("Hello "+message)

def fun2(message :str):
	print("Ciao "+message)
	
f = my_decorator(fun1)#my_decorator返回的是wapper函数(f就等于这个函数了),然后又将fun1作为参数先交给了func
f("volcano") #wapper接收volcano后先打印你好!,再将volcano传入fun1并返回Hello volcano
#output:你好! Hello volcano

#我们会发现上面最后的调用还是很麻烦,因此用@解决这一问题
####第三个版本
def my_decorator(func):#定义一个装饰器 传入函数名
	def wapper(s): #装饰器的重复功能函数
		print("你好!")
		return func(s)#返回传入函数的执行结果
	return wapper  #返回wapper函数

def fun1(message :str):
	print("Hello "+message)

def fun2(message :str):
	print("Ciao "+message)

@welcome  #相当于已经给fun1加上了my_decorator
fun1("volcano")#output:你好! Hello volcano
print(fun1) #output:<function my_decorator.<locals>.wapper at 0x000000000>可以看到这个函数的签名已经被装饰器包装起来了

一、小甲鱼
【2021.9.26】栈
【10.4】中缀表达变后缀表达
【10.5】分治
二、马士兵和左程云
【10.4】队列
三、python数据结构
【10.6】冒泡排序
快速排序 nlogn
【10.10】堆排序
二叉树的顺序存储:
①已知父节点序号i -->左孩子节点为2i+1
②已知父节点序号i -->右孩子节点为2i+2
③已知孩子节点序号为i -->父亲节点为(i-1)//2
大根堆:父亲大
小根堆:父亲小
堆得向下调整:左右都是堆,但是根节点不满足,通过一次向下调整可以变成一个合法堆
调整方法,选择最后一个节点放在顶点,然后向下调整
【10.12】堆排序代码
【10.26】挨个出数能够实现排序
对于解决topK问题复杂度也只是nlogK
【10.28】栈
【10.29】括号匹配
【10.31】队列
用列表实现队列不能循环存数,通过front/rear +1对maxsize取余可以实现循环
队空条件:rear == front
堆满条件: (rear+1)% maxsize == front
【11.1】链表
【11.4】哈希表
在直接寻址表的基础上引入哈希函数,让很大范围数的集合映射到一个很小的范围
当两个哈希函数结果值相同时 出现哈希冲突
为解决哈希冲突可以使用开放寻址法
使用拉链法解决哈希冲突,每一个位置放一个链表
【11.9】MD5是哈希表应用,百度网盘上传后会判断MD5值

树的度:最大节点数目
【11.15】二叉树
【11.16】二叉搜索树
迭代插入
【2022.7.7】链表、哈希表复习
【7.8】二叉搜索树
一个节点的左节点一定比当前节点值小
右节点一定比它大
【7.11】二叉搜索树的删除操作
①当删除节点没有叶子节点直接删除
②当删除的节点有1个孩子节点,将这个节点的孩子和父亲直接连接(设置成右子树)
特殊情况:当删除的节点是根节点时,重新设置孩子节点为根节点
③当删除的节点有2个孩子节点时,找到其右子树中最小节点删除(这个节点一定没有左孩子节点并且最多只有一个右孩子节点),并且替换当前节点。
【7.14】AVL树
是一颗自平衡的二叉搜索树,即是根的左右子树(都是平衡二叉树)的高度之差的绝对值不能超过1
插入一个节点可能会破坏AVL树的平衡,可以通过旋转操作来进行修正。
插入一个节点后,只有从插入节点到根节点的路径上的节点的平衡可能被改变。我们需要找出第一个破坏了平衡条件的节点,称之为K。K的两颗子树的高度差2。
不平衡的出现可能有四种情况:
AVL树的扩展应用 B树

贪心算法
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。
贪心算法并不保证会得到最优解,但是在某些问题上贪心算法的解就是最优解。要会判断—个问题能否用贪心算法来计算。
可解决 ①找零问题
②数字拼接问题
③活动选择问题
【7.17】动态规划
在解决斐波那契数列这样的问题时,如果使用递归就会产生重复计算子问题(f4=f3+f2,f3=f2+f1重复计算f2)导致时间复杂度过高2^n
使用动态规划法:用一个数组将以前的计算结果都保存下来
我们解决动态规划问题一般分为四步:
1、定义一个状态,这是一个最优解的结构特征
2、进行状态递推,得到递推公式
3、进行初始化
4、返回结果

四、饲养员

数组
在这里插入图片描述特点:读的快,写的慢

常用操作
a.insert(index,val)
a.remove(val)
a.pop(index)
a.pop()

链表
在这里插入图片描述
特点:写的很快,读的很慢
常用操作

linkedlist=deque()
linkedlist.append()
linkedlist.insert(index,val) O(N)
val=linkedlist[2] O(N)
linkedlist.index(99) O(N)
del linkedlist[index]
linkedlist.remove(val)

队列
在这里插入图片描述

peck()获取即将出队元素
pop()删除即将出队元素

哈希表=散列表
在这里插入图片描述
包括集合set

在这里插入图片描述
用列表创建stack

【8.31】KMP
暴力查找模式串时 文本串匹配指针会回溯
aabaabaaf
aabaaf
KMP使用Next数组解决这一问题
前缀:包含首字母 不包含尾字母的所有子串
后缀:包含尾字母 不包含首字母的所有子串
最长相等前后缀:a(0)aa(1) aab(0) aaba(1) aabaa(2) aabaaf(0)
KMP遇到不匹配时,查询当前位置next为多少,然后跳到对应模式串位置开始继续匹配
这是因为next代表当前位置前的最长相等前后缀长度,也就是说模式串已经在前面匹配到前缀了

求next数组步骤:
①初始化指针以及第一个位置
使用i指向后缀尾 j指向前缀尾
②for i到模式串长度循环
③当i与j不相同也就是前后缀不同时 :j回溯到next[j-1]的位置
当i与j相同 也就是前后缀相同时:j++ 赋值next[j]=j++ i++

五、 数据结构与算法-青岛大学

投了一篇,接了个助教的工作;继续学习
【10.13】串
串也是一个线性结构
和前面学习的不一样的地方在于其中的每个元素只能是字符;不能是整数或者小数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bu volcano

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值