Python数据结构与算法分析(第二版)学习笔记——导论习题

67 阅读7分钟

计算机科学研究的是能逐步解决问题的算法,算法就是一个解决方案。

抽象数据类型从逻辑上分析数据和其运算而不考虑具体的实现过程,数据结构是抽象数据类型的实现。

python面型对象编程

面向对象编程的python允许用户创建类来对解决问题需要的数据进行建模,通过创建类,我们可以很快捷的创建一系列需要的对象。类对象包含属性和方法,属性是类的特征,而方法则是解决问题的过程,比如说我们创建了一个人的类,那性别、身高、名字等特征就是属性,而唱、跳、rap就可以看成是方法。在创建类的时候,要先声明类,并进行初始化对象。

类提供了一系列默认方法供用户使用,不过用户也可以重写这些方法来满足更丰富的使用需要。要构造方法,总是将方法命名为__init__,需要注意的是,不要直接调用__init__。

class 类名:

课后练习:

1-9主要是创建一个表示分数的类,并逐步完善。 在创建类的时候,要先初始化对象,同时我们需要引入两个参数,其中top用来表示分子,botton表示分母,同时要注意分数形式中不能出现小数。

class Fraction:
    #初始化
    def __init__(self,top,botton):
        if int(top) != float(top) or int(botton) != float(botton):
            raise RuntimeError("你不能使用小数")
        self.top = top
        self.botton = botton

创建两个方法分别用来返回分子和分母,同时,重写 str 方法用来表达分数。python本身不提供分数的表达形式,因此我们要自己构建一个拼接字符串,涉及到数字的部分要注意将其格式化为字符串。这里的common是一个最大公因数,用来最简化分数。


def __str__(self):
    common = self.gcd(self.top,self.botton)
    return str(self.top//common) + "/" + str(self.botton//common)

def getNum(self):
    return self.top

# 返回分母
def getDem(self):
    return self.botton

我们需要一个用来计算最大公因数的算法,如果分子除分母余数为0,那么分母就是最大公因数,否则,我们就把分母作为分子,余数做分母继续计算,直到余数取0为止。

#最大公因私
def gcd(self,m,n):
    while m % n != 0:
        oldm = m
        oldn = n

        m = oldn
        n = oldm % oldn

    return n

在这个题目中,我们还要重写四则运算的规则,other代表另一个分数,同时不要忘记调用最大公因数来简化结果。在计算加减法的过程中,我们要给两个分数寻找一个共同的分母,因此我们的思路是分母相乘,分子分母交叉相乘。乘法直接相乘即可,而在计算除法的过程中,最好的方法是用一个分数乘另一个分数的倒数。

#最简加法
def __add__(self, other):
    newtop = self.top*other.botton + self.botton*other.top
    newbotton = self.botton * other.botton

    common = self.gcd(newtop,newbotton)
    return Fraction(newtop//common,newbotton//common)

#减法运算
def __sub__(self, other):
    newtop = self.top*other.botton - self.botton*other.top
    newbotton = self.botton * other.botton

    common = self.gcd(newtop,newbotton)
    return Fraction(newtop//common,newbotton//common)
# 乘法运算
def __mul__(self, other):
    newtop = self.top * other.top
    newbotton = self.botton * other.botton
    common = self.gcd(newtop, newbotton)
    return Fraction(newtop // common, newbotton // common)
# 除法运算
def __truediv__(self, other):
    newtop = self.top * other.botton
    newbotton = self.botton * other.top
    common = self.gcd(newtop, newbotton)
    return Fraction(newtop // common, newbotton // common)

第四题的内容对应的是两个分数的一系列大小比较,我们的思路是寻找共同的分母,比较分子,因此直接比较分子乘分母的大小,需要注意的是区分正负号。

# 判断原本的参数是否大于新的参数
def __gt__(self,other):
    if  self.top * other.botton * self.botton * other.botton >= 0:
        if self.top * other.botton > self.botton * other.botton:
            return True
        else:
            return False
    else:
        if self.top * self.botton > 0:
            return True
        else:
            return False
def __ge__(self,other):
    if self.top * other.botton * self.botton * other.botton >= 0:
        if self.top * other.botton > self.botton * other.botton:
            return True
        else:
            return False
    else:
        if self.top * self.botton > 0:
            return True
        else:
            return False
def __lt__(self,other):
    if self.top * other.botton * self.botton * other.botton >= 0:
        if self.top * other.botton  < self.botton * other.botton:
            return True
        else:
            return False
    else:
        if self.top * self.botton < 0:
            return True
        else:
            return False
def __le__(self,other):
    if self.top * other.botton * self.botton * other.botton >= 0:
        if self.top * other.botton <= self.botton * other.botton:
            return True
        else:
            return False
    else:
        if self.top * self.botton <= 0:
            return True
        else:
            return False

#     不等式判别
def __ne__(self,other):
    if self.top * other.botton != self.botton * other.botton:
        return True
    else:
        return False

__radd__ 是 Python 中的一个特殊方法(也称为魔术方法),用于实现右侧加法运算的行为。

__iadd__方法定义在类中,用于实现对象的原地加法运算(in- zplace addition)。我们可以将它看成是在__add__ 的基础上将原有的分数改成新的分数。- __repr__方法应该返回一个字符串,该字符串是一个有效的Python表达式,通过使用该字符串可以重新创建该对象。

def __radd__(self, other):
    newtop = self.top*other.botton +self.botton*other.top
    newbotton = self.botton*other.botton

    return Fraction(newtop,newbotton)

def __iadd__(self, other):
    newtop = self.top * other.botton + self.botton * other.top
    newbotton = self.botton * other.botton

    self.top = newtop
    self.botton = newbotton

def __repr__(self):
    return "这是分数"

第10题要求我们构造一个与门,我们考虑的问题包括输入的来源、输入的内容、输出的内容、结果的条件判断。与门需要两个输入,当逻辑来源不存在时,用None表示, self.pin = [None,None]表示有两个输入,self.name表示逻辑门的名字,方便我们在使用时加以区分, self.output代表输出结果。 setPin用来表示接口,我们有0,1两个接口pin_num,用来表示我们使用的接口,source表述输入。 getPin用来取得输入的值,如果值为None,我们就手动输入一个值。performGateLogic是一个逻辑判断,在这里我们输入两个值并判断结果,只用两个值皆为1时,该逻辑门返回1。def getOutput(self)用来返回结果。

与门(AND gate)是一种逻辑门电路,它接收两个输入信号并产生一个输出信号。只有当两个输入信号同时为逻辑高(1)时,输出信号才为逻辑高;否则,输出信号为逻辑低(0)。

image.png

#与门
class AndGate1:

    # 初始化,包含逻辑门的名字、输入、输出
    def __init__(self,name):
        self.name = name
        self.pin = [None,None]
        self.output = None

    # 接口,数据来源
    def setPin(self,source,pin_num):
        self.pin[pin_num] = source
    # 如果逻辑值存在就输出,否则手动输入
    def getPin(self,pin):
        if pin == None:
            return input("输入逻辑"+self.name)
        else:
            return self.getOutput()

    def performGateLogic(self):
        # 利用逻辑门输入判断结果
        self.pin[0] = self.getPin(self.pin[0])
        self.pin[1] = self.getPin(self.pin[1])
        if self.pin[0] == 1 and self.pin[1] == 1:
            return 1
        else:
            return 0
    # 输出
    def getOutput(self):
        self.output = self.performGateLogic()
        return self.output

或门(OR gate)是一种逻辑门电路,它接收两个输入信号并产生一个输出信号。只要两个输入信号中至少有一个为逻辑高(1),输出信号就为逻辑高;只有当两个输入信号同时为逻辑低(0)时,输出信号才为逻辑低。

image.png

class OrGate1:
    def __init__(self,name):
        self.name = name
        self.pin = [None,None]
        self.output = None
    def setpin(self,source,pin_num):
        self.pin[pin_num] = source
    def getpin(self,pin):
        if pin  == None:
            return int(input("输入逻辑"+self.name))
        else:
            return self.getoutput()

    def performGateLogic(self):
        self.pin[0] = self.getpin(self.pin[0])
        self.pin[1] = self.getpin(self.pin[1])
        if self.pin[0] == 1 or self.pin[1] == 1:
            return 1
        else:
            return 0
    def getoutput(self):
        self.output = self.performGateLogic()
        return self.output

非门(NOT gate),也称为反相器,是一种逻辑门电路,它接收一个输入信号并产生一个输出信号。非门的输出信号与输入信号相反,当输入信号为逻辑高(1)时,输出信号为逻辑低(0);当输入信号为逻辑低(0)时,输出信号为逻辑高。

image.png

class NOT:
    def __init__(self,name):
        self.name = name
        self.pin = None
        self.outpin = None

    def setpin(self,source):
        self.pin = source

    def getpin(self,pin):
        if pin == None:
            return int(input("输入逻辑"+self.name))
        else:
            return self.output()
    def performGateLogic(self):
        self.pin = self.getpin(self.pin)
        if self.pin == 1:
            return 0
        else:
            return 1

    def output(self):
        self.outpin = self.performGateLogic()
        return self.outpin

异或门(XOR gate)是一种逻辑门电路,它接收两个输入信号并产生一个输出信号。异或门的输出信号在两个输入信号不相等时为逻辑高(1),在两个输入信号相等时为逻辑低(0)。

image.png

class XOR_gate:
    def __init__(self,name):
        self.name = name
        self.pin = [None,None]
        self.output = None
    def setpin(self,source,pin_num):
        self.pin[pin_num] = source
    def getpin(self,pin):
        if pin  == None:
            return int(input("输入逻辑"+self.name))
        else:
            return self.getoutput()

    def performGateLogic(self):
        self.pin[0] = self.getpin(self.pin[0])
        self.pin[1] = self.getpin(self.pin[1])
        if self.pin[0] == self.pin[1]:
            return 0
        else:
            return 1
    def getoutput(self):
        self.output = self.performGateLogic()
        return self.output

半加器(Half Adder)是一种组合逻辑电路,用于对两个输入位进行加法运算,并产生两个输出位:和位(Sum)和进位位(Carry)。

image.png

class XOR_gate:
    def __init__(self,a,b):
        self.a = a
        self.b = b
        self.sum()
        self.carrybit()

    def sum(self):
        if self.a == self.b:
            print("s=0")
        else:
            print("s=1")
    def carrybit(self):
        if self.a == 1 and self.b == 1:
            print("c=1")
        else:
            print("C=0")

用一个简单的逻辑电路表示半加器:

class AndGate2:
    def cal(self,a,b):
        self.pin = [a,b]
        if self.pin[0] == 1 and self.pin[1] == 1:
            return 1
        else:
            return 0

class OrGate2:
    def cal(self,a,b):
        self.pin = [a, b]
        if self.pin[0] == 1 or self.pin[1] == 1:
            return 1
        else:
            return 0
class NoGate2:
    def cal(self,a):
        self.pin = a
        if self.pin == 1 :
            return 0
        else:
            return 1

g1 = AndGate2()
g2 = OrGate2()
g3 = NoGate2()
# 半加器
carry = g1.cal(1,1)

print(carry)
sum = g2.cal(g1.cal(1,1),g3.cal(g1.cal(1,1)))
print(sum)

全加器(Full Adder)是一种组合逻辑电路,用于对三个输入位进行加法运算,并产生两个输出位:和位(Sum)和进位位(Carry)。

image.png

class Full_Adder:
    def __init__(self,a,b,c):
        self.a = a
        self.b = b
        self.c = c
        self.sum()
        self.carrybit()


    def sum(self):
        if self.a == self.b:
            if self.c == 0:
                print("s=0")
            else:
                print("s=1")
        else:
            if self.c == 1:
                print("s=0")
            else:
                print("s=1")
    def carrybit(self):
        if self.a == self.b :
            print("c=1")
        else:
            print("C=0")