数据结构与算法 学习笔记(1)- 基础知识

数据结构与算法 学习笔记 (1) - 基础知识

作为计算机科学与技术领域核心之一,数据结构与算法对程序的设计具有重要的作用,因此值得深入学习。本系列文章以《数据结构与算法:Python语言描述》,LeetCode,剑指offer等为基础,记录下完整的学习过程。
此次文章内容主要涉及数据结构与算法的基础问题,以及python语言的一些特性。

一、算法及算法分析

1.1 问题,问题实例,算法

问题:一个需要解决的具体需求称作问题W。例如判断一个正整数是否为素数就是一个问题。 问题实例:问题W的一个具体例子w。例如判断13是否为素数。 算法:解决问题W的一个算法A,是对求解过程的严格描述。对于问题W的任意一个实例w,实施算法A,就能得到w的解。

1.2 算法分析与度量

算法的度量分为空间开销和时间开销,在此我们以时间开销为例,描述算法的度量。首先我们假设计算中的一次基本操作消耗一个时间单位,我们以基本操作的次数来衡量时间开销(时间复杂度),时间复杂度用大O记法表示。若n为问题规模,有:

基本操作:常量时间操作,其时间复杂度为O(1);
加法规则:如果算法是多个部分的顺序复合,其复杂性为各部分复杂性之和;
乘法规则:如果算法是一个循环,循环体执行T1(n)次,每次执行T2(n)时间,那么其时间复杂度为O(T1(n)* T2(n));
最大规则:如果算法是条件分支,取时间复杂度最大的分支作为复杂度度量,为O(max(T1(n),T2(n)).

二、数据结构

2.1 结构性与功能性

常见的线性结构、树结构和图结构这些数据结构对数据元素之间的相互关系做了一些规定,我们称之为结构性数据结构。而功能性数据结构主要包括栈、队列、字典等,这些数据结构不涉及元素如何存储、元素之间如何关联,都支持以某一套方式存储和访问。

2.2 Python内置数据结构

Python变量和对象:在Python程序里,给变量约束一个对象,就是把该对象的标识(内存位置)存入到变量中,这种方式称为引用语义。有些语言采用的不是引用语义,而是把值直接存入到变量的存储区里,这种方式称为值语义,例如C语言采用的就是值语义。引用语义变量所需的存储空间大小一致,因为只需存入一个引用。

三、 Python特性

3.1 继承,派生

定义新类时,可以列出一个或几个已知类作为被继承的类,这样就建立了新类与已知类之间的继承关系。定义已知类为基类(父类),新类为派生类(子类),派生类继承基类的所有功能,可以使用或修改基类已有的功能,也可以增加新的数据和功能。例如:

class MyStr(str):#派生类定义
    pass #语句组
s=MyStr(1234)
print(issubclass(MyStr,str))#1
print(isinstance(s,MyStr))#2
print(isinstance(s,str))#3

True
True
True
以上代码就定义了一个基类为str类,派生类为MyStr类的新类。语句1,2,3的输出表明,Mystr是str的派生类,s是Mystr类,s也是str类。

3.2 方法查找

当派生类调用类方法时,会从当前派生类开始,查找索要调用的方法,如果未找到,则向基类查找该方法,依次类推,如果最终未找到,Python解释器将报AttributeError异常,如果找到了该方法,则会调用它。

另外,当派生类中重新定义了基类中已有的方法时,则实例对象将默认使用新的方法,基类中的方法不再被使用。例如:

class A:
    def __init__(self):
        pass
    def f(self):
        self.g()
    def g(self):
        print("A.g() called")
class B(A):
    def __init__(self):
        A.__init__(self)
    def g(self):
        print("B.g() called")
x,y,z=A(),B(),B()
x.g() #1
y.g() #2
z.f() #3

A.g() called
B.g() called
B.g() called
语句一的输出,表明x.g()调用的是类A中的g方法,语句2的输出表明调用的是B中的g方法,语句3的输出表明,z.f()先是调用A类中的方法f,然后再调用了B类中的方法g。这就说明,在派生类中,若重新定义了基类中的方法,调用时默认调用派生类中的同名方法(因为z是派生类B的对象),我们把这种查找方式称为动态约束,而如果z.f最终调用的是类A中的方法g时,我们称之为静态约束(绑定)。Python中使用的是动态约束,我们把通过动态约束确定调用关系的函数称为虚函数。

3.3 标准函数super()

Python内置了一个函数super(),在派生类里使用super()方法,则属性查找将从派生类的基类开始,而不是从派生类开始。super函数最简单的一种使用方式是,不指定super()的参数,则其默认从派生类的上一层基类开始属性查找。例如:

class A:
    def __init__(self):
        pass
    def f(self):
        self.g()
    def g(self):
        print("A.g() called")
class B(A):
    def __init__(self):
        A.__init__(self)
    def g(self):
        super().g()
x,y,z=A(),B(),B()
x.g() #1
y.g() #2
z.f() #3

A.g() called
A.g() called
A.g() called
以上代码显示的是super()函数,会直接从基类的方法开始查找,即使对象是派生类的实例,另外,super函数的另一种用法是指定从哪一种类开始查找, 用法为super(C,obj),C为类,obj为C类实例,这样属性查找将从C类的基类开始往上查找。其它更复杂的super()函数用法这里就不做介绍啦。

四、说明

本文相应的代码及资料已经以.ipynb文件和.pdf形式在github中给出。

github地址:https://github.com/LSayhi/Algorithms

点击【阅读原文】,github传送门

数据结构与算法 学习笔记(1)- 基础知识_第1张图片

你可能感兴趣的:(数据结构与算法)