《Python数据结构与算法分析》学习笔记

目录

  • 第一章 导论
    • 1.4 Python数据
      • 1.4.1 内建集合数据类型
        • 1.4.1.1 列表
        • 1.4.1.2 字符串
        • 1.4.1.3 集合
        • 1.4.1.4 字典
      • 1.4.3 控制结构
      • 1.4.6 定义类
        • 1.4.6.1 Fraction类
        • 1.4.6.2 继承:逻辑门与电路
    • 1.8 练习题

第一章 导论

介绍抽象数据类型,复习Python。

1.4 Python数据

1.4.1 内建集合数据类型

1.4.1.1 列表

运算:索引([ ])、连接(+)、重复(*)、成员(in)、长度(len)、切片([:])
方法:append、insert、pop、sort、reverse、del、index、count、remove。
del(l[index]):删除索引号index的元素,无返回值
l.pop():删除最后一个值,并返回
l.remove(item):移除列表中第一次出现的item

1.4.1.2 字符串

方法:.center(w); .count(item); .ljust(w); .rjust(w); .lower(); .upper(); .find(item); .split(schar)

1.4.1.3 集合

运算:成员(in)、长度(len)、|、&、<=、-
方法:.union(otherset)、 .intersection(.otherset)、 .issubset(otherset)、 .difference(otherset); .add(item); .remove(item); .pop(); .cleat()

1.4.1.4 字典

运算符:[ ]、in、del
方法:.keys(); .values(); .items(), .get(key); .get(key, alt)

1.4.3 控制结构

列表解析式:
sqlist = [x*x for x in range(1,11) if x%2 !=0]

1.4.6 定义类

1.4.6.1 Fraction类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
class Fraction:
    # 构造方法
    def __init__(self, top, bottom):
        '''
        top: 分子
        bottom: 分母
        '''
        if all([isinstance(x,int) for x in [top,bottom]]):
            common = self.gcd(top,bottom)
            label = (top*bottom)//abs(top*bottom)
            self.num = label*abs(top//common)
            self.den = abs(bottom//common)
        else:
            raise TypeError("分子分母必须都为整数")
    # str(),print() 给用户看的,用于显示内容
    def __str__(self):
        return "{}/{}".format(self.num,self.den)
   
    # repr(),Fraction 用于调试和开发,复现obj = eval()
    def __repr__(self):
        return "Fraction({},{})".format(self.num,self.den)
   
    # 加法
    def __add__(self,otherfraction):
        newnum = self.num*otherfraction.den+self.den*otherfraction.num
        newden = self.den * otherfraction.den
        # common = self.gcd(newnum,newden)
        # return Fraction(newnum//common,newden//common)
        return(Fraction(newnum,newden))
     
    # 右加
    def __radd__(self,otherfraction):
        newnum = self.num*otherfraction.den+self.den*otherfraction.num
        newden = self.den * otherfraction.den
        return(Fraction(newnum,newden))
       
    # +=
    # def __iadd__(self,otherfraction):
        ## newnum = self.num*otherfraction.den+self.den*otherfraction.num
        ## newden = self.den * otherfraction.den
        # self = (Fraction(newnum,newden))
        # self = self.__add__(self,otherfraction)
       
    # 减法
    def __sub__(self,otherfraction):
        return self.__add__(Fraction(-otherfraction.num,
        otherfraction.den))
   
    # 乘法
    def __mul__(self,otherfraction):
        newnum = self.num * otherfraction.num
        newden = self.den * otherfraction.den
        return Fraction(newnum, newden)
       
    # 除法
    def __truediv__(self,otherfraction):
        return self.__mul__(Fraction(otherfraction.den,
        otherfraction.num))
   
   
    # 等于
    def __eq__(self,other):
        first = self.num * other.den
        second = other.num * self.den
        return first == second
       
    # 不等
    def __ne__(self,other):
        first = self.num * other.den
        second = other.num * self.den
        return first != second
       
    # 大于
    def __gt__(self,other):
        first = self.num * other.den
        second = other.num * self.den
        return first > second    
   
    # 大于等于
    def __ge__(self,other):
        first = self.num * other.den
        second = other.num * self.den
        return first >= second    

    # 小于
    def __lt__(self,other):
        first = self.num * other.den
        second = other.num * self.den
        return first < second    

    # 小于等于
    def __le__(self,other):
        first = self.num * other.den
        second = other.num * self.den
        return first <= second            
   
    # 求解最大公因子
    def gcd(self,m,n):
        while m % n!=0:
            oldm = m
            oldn = n
           
            m = oldn
            n = oldm%oldn
        return n
       
    # 返回分子
    def getNum(self):
        return self.num
   
    # 返回分母:
    def getDen(self):
        return self.den
       
    # 复制
    def copy(self):
        return Fraction(self.num,self.den)
if __name__=="__main__":
    f1 = Fraction(4,5)
    print(f1)
    f2 = Fraction(2,-4)
    print(f2)

    print("f1+f2:", f1+f2)
    print("f1-f2:", f1-f2)
    print("f1*f2:", f1*f2)
    print("f1/f2:", f1/f2)
    f1+=f2
    print("f1+=f2", f1)
    print("==",f1==f2)
    print("!=",f1!=f2)
    print(">",f1>f2)
    print(">=",f1>=f2)
    print("<",f1<f2)
    print("<=",f1<=f2)

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
4/5
-1/2
f1+f2: 3/10
f1-f2: 13/10
f1*f2: -2/5
f1/f2: -8/5
f1+=f2 3/10
== False
!= True
> True
>= True
< False
<= False

在命令行中输入变量名显示__repr__:

1
2
3
4
5
>>> from Fraction import Fraction
>>> f1 = Fraction(-3,2)
>>> f1
Fraction(-3,2)
>>>

1.4.6.2 继承:逻辑门与电路

IS-A用于描述子类和父类关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# 超类LogicGate
class LogicGate:

    def __init__(self,n):
        self.label = n
        self.output = None
   
    def getLabel(self):
        return self.label
       
    def getOutput(self):
        self.output = self.performGateLogic()
        return self.output
       
# 二引脚逻辑门
class BinaryGate(LogicGate):

    def __init__(self,n):
        super().__init__(n)
       
        self.pinA = None
        self.pinB = None
       
    def getPinA(self):
        return int(input("Enter Pin A for gate" + self.getLabel() + "-->"))
       
    def getPinB(self):
        return int(input("Enter Pin B for gate" + self.getLabel() + "-->"))
       

# 单引脚逻辑门
class UnaryGate(LogicGate):
   
    def __init__(self,n):
        super().__init__(n)
       
        self.pin = None
       
    def getPin(self):
        return int(input("Enter Pin for gate" + self.getLabel() + "-->"))    
       
# 与门
class AndGate(BinaryGate):
   
    def __init__(self,n):
        super().__init__(n)
       
    def performGateLogic(self):
        self.pinA = self.getPinA()
        self.pinB = self.getPinB()
        if self.pinA == 1 and self.pinB == 1:
            return 1
        else:
            return 0
 
# 或门
class OrGate(BinaryGate):
   
    def __init__(self,n):
        super().__init__(n)
       
    def performGateLogic(self):
        self.pinA = self.getPinA()
        self.pinB = self.getPinB()
        if self.pinA == 1 or self.pinB == 1:
            return 1
        else:
            return 0
# 非门
class NotGate(UnaryGate):
    def __init__(self,n):
        super().__init__(n)
       
    def performGateLogic(self):
        self.pin = self.getPin()
        if self.pin==1:
            return 0
        else:
            return 1



if __name__=="__main__":
    g1 = AndGate("G1")
    print(g1.getOutput())
    g2 = OrGate("G2")
    print(g2.getOutput())
    g3 = NotGate("G3")
    print(g3.getOutput())

HAS-A关系 (HAS-A意即“有一个”)
连接器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# 超类LogicGate
class LogicGate:

    def __init__(self,n):
        self.label = n
        self.output = None
   
    def getLabel(self):
        return self.label
       
    def getOutput(self):
        self.output = self.performGateLogic()
        return self.output
       
# 二引脚逻辑门
class BinaryGate(LogicGate):

    def __init__(self,n):
        super().__init__(n)
       
        self.pinA = None
        self.pinB = None
       
    def getPinA(self):
        if self.pinA == None:
            return int(input("Enter Pin A for gate" + self.getLabel() + "-->"))
        else:
            return self.pinA.getFrom().getOutput()
       
    def getPinB(self):
        if self.pinB == None:
            return int(input("Enter Pin B for gate" + self.getLabel() + "-->"))
        else:
            return self.pinB.getFrom().getOutput()

    def setNextPin(self,source):
        if self.pinA == None:
            self.pinA = source
        else:
            if self.pinB == None:
                self.pinB = source
            else:
                raise RuntimeError("Error: NO EMPTY PINS")
       

# 单引脚逻辑门
class UnaryGate(LogicGate):
   
    def __init__(self,n):
        super().__init__(n)
       
        self.pin = None
       
    def getPin(self):
        if self.pin == None:
            return int(input("Enter Pin for gate" + self.getLabel() + "-->"))  
        else:
            return self.pin.getFrom().getOutput()
       
    def setNextPin(self,source):
        if self.pin == None:
            self.pin = source
        else:
            print("Cannot Connect: NO EMPTY PINS on this gate")
       
# 与门
class AndGate(BinaryGate):
   
    def __init__(self,n):
        super().__init__(n)
       
    def performGateLogic(self):
        self.pinA = self.getPinA()
        self.pinB = self.getPinB()
        if self.pinA == 1 and self.pinB == 1:
            return 1
        else:
            return 0
           
# 与非门
class NandGate(BinaryGate):
   
    def __init__(self,n):
        super().__init__(n)
   
    def performGateLogic(self):
        self.pinA = self.getPinA()
        self.pinB = self.getPinB()
        if self.pinA == 1 and self.pinB == 1:
            return 0
        else:
            return 1
           
# 或非门
class NorGate(BinaryGate):
   
    def __init__(self,n):
        super().__init__(n)
   
    def performGateLogic(self):
        self.pinA = self.getPinA()
        self.pinB = self.getPinB()
        if self.pinA == 0 and self.pinB == 0:
            return 1
        else:
            return 0
   
 
# 或门
class OrGate(BinaryGate):
   
    def __init__(self,n):
        super().__init__(n)
       
    def performGateLogic(self):
        self.pinA = self.getPinA()
        self.pinB = self.getPinB()
        if self.pinA == 1 or self.pinB == 1:
        # pinA = self.getPinA()
        # pinB = self.getPinB()
        # if pinA == 1 or pinB == 1:
            return 1
        else:
            return 0
           
# 异或门
class NorGate(BinaryGate):
   
    def __init__(self,n):
        super().__init__(n)
   
    def performGateLogic(self):
        self.pinA = self.getPinA()
        self.pinB = self.getPinB()
        if self.pinA == self.pinB:
            return 0
        else:
            return 1
           
# 非门
class NotGate(UnaryGate):
    def __init__(self,n):
        super().__init__(n)
       
    def performGateLogic(self):
        self.pin = self.getPin()
        if self.pin==1:
            return 0
        else:
            return 1

class Connector():
    def __init__(self,fgate,tgate):
        self.fromgate = fgate
        self.togate = tgate
       
        tgate.setNextPin(self)
       
    def getFrom(self):
        return self.fromgate
     
    def getTo(self):
        return self.togate
       


if __name__=="__main__":
    g1 = AndGate("G1")
    g2 = AndGate("G2")
    g3 = OrGate("G3")
    g4 = NotGate("G4")
   
    c1 = Connector(g1,g3)
    c2 = Connector(g2,g3)
    c3 = Connector(g3,g4)
   
    print(g4.getOutput())

1.8 练习题

  1. 实现简单的方法getNum 和getDen ,它们分别返回分数的分子和分母。
  2. 如果所有分数从一开始就是最简形式会更好。修改Fraction 类的构造方法,立即使用最大公因数来化简分数。注意,这意味着__add__
    不再需要化简结果。
  3. 实现下列简单的算术运算:submul 和__truediv__ 。
  4. 实现下列关系运算:gtgeltle 和__ne__ 。
  5. 修改Fraction 类的构造方法,使其检查并确保分子和分母均为整数。如果任一不是整数,就抛出异常。
  6. 我们假设负的分数是由负的分子和正的分母构成的。使用负的分母会导致某些关系运算符返回错误的结果。一般来说,这是多余的限制。请修改构造方法,使得用户能够传入负的分母,并且所有的运算符都能返回正确的结果。
  7. 研究__radd__ 方法。它与__add__ 方法有何区别?何时应该使用它?请动手实现__radd__ 。
  8. 研究__iadd__ 方法。它与__add__ 方法有何区别?何时应该使用它?请动手实现__iadd__ 。
  9. 研究__repr__ 方法。它与__str__ 方法有何区别?何时应该使用它?请动手实现__repr__ 。
  10. 研究其他类型的逻辑门(例如与非门、或非门、异或门)。将它们加入电路的继承层次结构。你需要额外添加多少代码?
  11. 最简单的算术电路是半加器。研究简单的半加器电路并实现它。 将半加器电路扩展为8位的全加器。
  12. 本章展示的电路模拟是反向工作的。换句话说,给定一个电路,其输出结果是通过反向访问输入值来产生的,这会导致其他的输出值被反向查询。这个过程一直持续到外部输入值被找到,此时用户会被要求输入数值。修改当前的实现,使电路正向计算结果。当收到输入值的时候,电路就会生成输出结果。
  13. 设计一个表示一张扑克牌的类,以及一个表示一副扑克牌的类。使用这两个类实现你最喜欢的扑克牌游戏。
  14. 在报纸上找到一个数独游戏,并编写一个程序求解。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# 电路正向计算&半加器
# 超类LogicGate
class LogicGate:

    def __init__(self,n):
        self.label = n
        self.output = None
   
    def getLabel(self):
        return self.label
       
    def getOutput(self):
        self.output = self.performGateLogic()
        return self.output
       
# 二引脚逻辑门
class BinaryGate(LogicGate):

    def __init__(self,n,pinA=None,pinB=None):
        super().__init__(n)
       
        self.pinA = pinA
        self.pinB = pinB
        self.output = self.getOutput()
       
    # def getPinA(self):
        # if self.pinA == None:
            # return int(input("Enter Pin A for gate" + self.getLabel() + "-->"))
        # else:
            # return self.pinA.getFrom().getOutput()
       
    # def getPinB(self):
        # if self.pinB == None:
            # return int(input("Enter Pin B for gate" + self.getLabel() + "-->"))
        # else:
            # return self.pinB.getFrom().getOutput()
           
    def __str__(self):
        return "{} - pinA: {}; pinA: {}; output: {}".format(self.label,self.pinA, self.pinB,self.output)

    def setNextPin(self,source):
        if self.pinA == None:
            self.pinA = source.output
        else:
            if self.pinB == None:
                self.pinB = source.output
            else:
                raise RuntimeError("Error: NO EMPTY PINS")
       

# 单引脚逻辑门
class UnaryGate(LogicGate):
   
    def __init__(self,n,pin=None):
        super().__init__(n)
       
        self.pin = None
        self.output = self.getOutput()
    # def getPin(self):
        # if self.pin == None:
            # return int(input("Enter Pin for gate" + self.getLabel() + "-->"))  
        # else:
            # return self.pin.getFrom().getOutput()
           
    def __str__(self):
        return "{} - pin: {}; output: {}".format(self.label,self.pin,self.output)

       
    def setNextPin(self,source):
        if self.pin == None:
            self.pin = source.output
        else:
            print("Cannot Connect: NO EMPTY PINS on this gate")
       
# 与门
class AndGate(BinaryGate):
   
    def __init__(self,n,pinA=None, pinB=None):
        super().__init__(n,pinA,pinB)
       
    def performGateLogic(self):
        # self.pinA = self.getPinA()
        # self.pinB = self.getPinB()
        if self.pinA == 1 and self.pinB == 1:
            return 1
        else:
            return 0
           
# 与非门
class NandGate(BinaryGate):
   
    def __init__(self,n,pinA=None, pinB=None):
        super().__init__(n,pinA,pinB)
   
    def performGateLogic(self):
        # self.pinA = self.getPinA()
        # self.pinB = self.getPinB()
        if self.pinA == 1 and self.pinB == 1:
            return 0
        else:
            return 1
           
# 或门
class OrGate(BinaryGate):
   
    def __init__(self,n,pinA=None, pinB=None):
        super().__init__(n,pinA,pinB)
       
    def performGateLogic(self):
        # self.pinA = self.getPinA()
        # self.pinB = self.getPinB()
        if self.pinA == 1 or self.pinB == 1:
        # pinA = self.getPinA()
        # pinB = self.getPinB()
        # if pinA == 1 or pinB == 1:
            return 1
        else:
            return 0
           
# 或非门
class NorGate(BinaryGate):
   
    def __init__(self,n,pinA=None, pinB=None):
        super().__init__(n,pinA,pinB)
   
    def performGateLogic(self):
        # self.pinA = self.getPinA()
        # self.pinB = self.getPinB()
        if self.pinA == 0 and self.pinB == 0:
            return 1
        else:
            return 0
   
 

           
# 异或门
class NorGate(BinaryGate):
   
    def __init__(self,n,pinA=None,pinB=None):
        super().__init__(n,pinA,pinB)
   
    def performGateLogic(self):
        # self.pinA = self.getPinA()
        # self.pinB = self.getPinB()
        if self.pinA == self.pinB:
            return 0
        else:
            return 1
           
# 非门
class NotGate(UnaryGate):
    def __init__(self,n,pin=None):
        super().__init__(n,pin)
       
    def performGateLogic(self):
        # self.pin = self.getPin()
        if self.pin==1:
            return 0
        else:
            return 1

class Connector():
    def __init__(self,fgate,tgate):
        self.fromgate = fgate
        self.togate = tgate
       
        tgate.setNextPin(fgate)
       
    def getFrom(self):
        return self.fromgate
     
    def getTo(self):
        return self.togate
       
class HalfAdder():
   
    def __init__(self,n,A,B):
        self.label = n
        self.A = A
        self.B = B
        self.S = NorGate("n1",A,B).output
        self.C = AndGate("n2",A,B).output
       
    def __str__(self):
        return "{} - A: {}; B: {}; S: {}; C: {}".format(self.label,self.A,self.B,self.S,self.C)
   
class Adder():

    def __init__(self,)

if __name__=="__main__":
    # g1 = AndGate("G1",0,1)
    # g2 = AndGate("G2",1,1)
    # g3 = OrGate("G3")
    # g4 = NotGate("G4")
   
    # c1 = Connector(g1,g3)
    # c2 = Connector(g2,g3)
    # c3 = Connector(g3,g4)
    # print(g1)
    # print(g2)
    # print(g3)
    # print(g4)
    # print(g4.output)
    h1 = HalfAdder("h1",0,0)
    h2 = HalfAdder("h2",0,1)
    h3 = HalfAdder("h3",1,0)
    h4 = HalfAdder("h4",1,1)
    print(h1)
    print(h2)
    print(h3)
    print(h4)