-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
239 lines (115 loc) · 329 KB
/
search.xml
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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>An introduction to approximation algorithms</title>
<link href="/post/e0de8bd7.html"/>
<url>/post/e0de8bd7.html</url>
<content type="html"><![CDATA[<p>本节取自《The Design ofApproximation-Algorithms》第一章,介绍了近似算法的一些基本定义并以<spanclass="math inline">\(set \quad cover\)</span>问题为例,使用了一些常用的技巧来设计近似算法。</p><h1 id="专业名词">专业名词</h1><ul><li><p><strong>discrete optimization:离散优化</strong></p><ul><li>应用于安排课程、计划运输路线等一系列<spanclass="math inline">\(NP-hard\)</span>问题(没有多项式时间的解)</li><li>解决<span class="math inline">\(NP-hard\)</span>问题的方法:<ol type="1"><li>限制算法是多项式时间的</li><li>放弃寻找最优解,而是去寻找足够好的解。</li><li>对于现实中复杂的问题,研究其理想化的版本。如模拟退火算法(simulatedannealing)、遗传算法(genetic algorithms)、禁忌搜索(tabusearch)</li></ol></li></ul></li><li><p><strong>heuristics andmetaheuristics:启发式和元启发式</strong></p><ul><li><p><strong>启发式算法</strong></p><p>一个基于直观或经验构造的算法,在可接受的花费(指计算时间和空间)下给出待解决组合优化问题每一个实例的一个可行解,该可行解与最优解的偏离程度一般不能被预计。</p></li><li><p><strong>元启发式算法</strong></p><p>一类通用型的启发式算法,这类算法的优化机理不过分依赖于算法的组织结构信息,可以广泛的应用到函数的组合优化和函数计算中</p></li><li><p><strong>近似算法和启发式算法的区别</strong></p><p>近似算法通常能得到一个有质量保证的解。启发式算法通常可在传统解决问题的经验中找到寻求一种面向问题的策略,之后用这种策略来在可行时间内寻找一个相对比较好的解,但对解的质量没有保证。</p></li></ul></li></ul><h1 id="p问题np问题npc问题">P问题、NP问题、NPC问题</h1><ul><li><p><strong>多项式时间</strong>(polynomialtime):可用多项式表示的时间复杂度,如<spanclass="math inline">\(O(1)\)</span>、<span class="math inline">\(O(\logN)\)</span>、<span class="math inline">\(O(N^2)\)</span></p></li><li><p><strong>约化</strong>(Reducibility):问题<spanclass="math inline">\(A\)</span>可以约化为问题<spanclass="math inline">\(B\)</span>,即用问题<spanclass="math inline">\(B\)</span>的方法解决问题<spanclass="math inline">\(A\)</span>,此约化是多项式的。例:用求解一元一次方程的方法约化为求解一元二次方程的方法。</p></li><li><p><strong><spanclass="math inline">\(P\)</span>问题</strong>:一类可在多项式时间内解决的问题的集合。</p></li><li><p><strong><spanclass="math inline">\(NP\)</span>问题</strong>:一类问题,此类问题可在多项式时间内验证。</p></li><li><p><strong><spanclass="math inline">\(NP-Complete\)</span>问题</strong>:一类问题<spanclass="math inline">\(X\)</span>,任意<spanclass="math inline">\(NP\)</span>问题<spanclass="math inline">\(Y\)</span>都可以在多项式式时间内约化为问题<spanclass="math inline">\(X\)</span>。</p><ul><li><p><strong>证明一个问题是<spanclass="math inline">\(NPC\)</span>问题:</strong></p><ol type="1"><li>此问题为<span class="math inline">\(NP\)</span>问题</li><li>一个已知的<spanclass="math inline">\(NPC\)</span>问题可以约化为此问题</li></ol></li><li><p><strong>Pick all the correct statements.If a problem <spanclass="math inline">\(H\)</span> is <spanclass="math inline">\(NP-Complete\)</span>, then...</strong></p><p>☑For any problem <span class="math inline">\(L\)</span> in <spanclass="math inline">\(NP\)</span>, there is a polynomial-time reductionfrom <span class="math inline">\(L\)</span> to <spanclass="math inline">\(H\)</span>.</p><p>☑For any problem <span class="math inline">\(L\)</span> in <spanclass="math inline">\(P\)</span>, there is a polynomial-time reductionfrom <span class="math inline">\(L\)</span> to <spanclass="math inline">\(H\)</span>.</p><p>☐<span class="math inline">\(H\)</span> belongs to the class <spanclass="math inline">\(P\)</span>.</p><p>☑<span class="math inline">\(H\)</span> belongs to the class <spanclass="math inline">\(NP\)</span>.</p><p>☑If there exists a polynomial-time algorithm for the Hamiltonian pathproblem then there exists a polynomial-time algorithm for <spanclass="math inline">\(H\)</span>.</p><p>☑An output to problem H is either "yes" or "no".</p><p>☑If there exists a polynomial-time algorithm for H then there existsa polynomial-time algorithm for the Hamiltonian path problem.</p></li></ul></li><li><p><strong><spanclass="math inline">\(NP-Hard\)</span>问题</strong>:一类问题所组成的集合,此类问题的范围比<spanclass="math inline">\(NPC\)</span>问题广,不一定为决策问题,不包含于<spanclass="math inline">\(NP\)</span>问题。任何<spanclass="math inline">\(NPC\)</span>问题可在多项式时间内约化为<spanclass="math inline">\(NP-Hard\)</span>问题。</p><ul><li><p><strong>Pick all the correct statements.If a problem <spanclass="math inline">\(H\)</span> is <spanclass="math inline">\(NP-Hard\)</span>, then...</strong></p><p>☑For any problem <span class="math inline">\(L\)</span> in <spanclass="math inline">\(P\)</span>, there is a polynomial-time reductionfrom <span class="math inline">\(L\)</span> to <spanclass="math inline">\(H\)</span>.</p><p>☐<span class="math inline">\(H\)</span> belongs to the class <spanclass="math inline">\(P\)</span>.</p><p>☐<span class="math inline">\(H\)</span> belongs to the class <spanclass="math inline">\(NP\)</span>.</p><p>☑If there exists a polynomial-time algorithm for <spanclass="math inline">\(H\)</span> then there exists a polynomial-timealgorithm for the Hamiltonian path problem.</p><p>☐If there exists a polynomial-time algorithm for the Hamiltonian pathproblem then there exists a polynomial-time algorithm for <spanclass="math inline">\(H\)</span>.</p><p>☐An output to problem <span class="math inline">\(H\)</span> is "yes"or "no".</p><p>☑For any problem <span class="math inline">\(L\)</span> in <spanclass="math inline">\(NP\)</span>, there is a polynomial-time reductionfrom <span class="math inline">\(L\)</span> to <spanclass="math inline">\(H\)</span>.</p></li></ul></li></ul><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230107212557061.png" /></p><p>[<imgsrc="../images/An-introduction-to-approximation-algorithms/u=2541031885,1494691757&fm=253&fmt=auto&app=138&f=JPG.jpeg" /></p><h1 id="近似算法">近似算法</h1><h2 id="定义">定义</h2><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230213143453547.png" /></p><ul><li>性能保证(performance guarantee)/近似比(approximationratio)/近似因子(approximation factor):<spanclass="math inline">\(\alpha\)</span><ul><li>对于最大化问题:<spanclass="math inline">\(\alpha<1\)</span></li><li>对于最小化问题:<spanclass="math inline">\(\alpha>1\)</span></li></ul></li><li>Ex:一个最大化问题的<span class="math inline">\(1/2-approximation\quad algorithm\)</span><ul><li>此算法的输出值<span class="math inline">\(S\geq(1/2)S^*\)</span></li></ul></li></ul><h2 id="近似算法的意义">近似算法的意义</h2><ul><li>近似算法可用于不需要得到最优解的<spanclass="math inline">\(NP-hard\)</span>问题</li><li>近似算法关注于理想化的模型,通过定理的证明可以对问题结构更深刻的思考,可以启发人们设计出解决实际问题的启发式算法</li><li>启发式和元启发式算法是通过经验设计出来的,近似算法有严谨的数学证明</li><li>可以通过近似算法来度量不同优化问题的难易程度</li></ul><h2 id="ptas">PTAS</h2><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230213203456983.png" /></p><h2 id="max-snp-hard-problem">MAX SNP-hard problem</h2><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230213204018687.png" /></p><h1 id="the-set-cover-problem">the set cover problem</h1><ul><li><p><strong>Definition</strong></p><ul><li><p><strong>Input:</strong></p><p>集合<span class="math inline">\(E=\left\{e_1, \ldots,e_n\right\}\)</span></p><p><span class="math inline">\(S_1, S_2, \ldots, S_m\)</span>,<spanclass="math inline">\(each \quad S_j \subseteq E\)</span></p><p>权重<span class="math inline">\(w_j \geq 0\)</span>,<spanclass="math inline">\(for \quad each \quad S_j\)</span></p></li><li><p><strong>Goal:</strong>找到一个权重最小的覆盖子集,即寻找一个满足<spanclass="math inline">\(\bigcup_{j \in I} S_j=E\)</span>的子集<spanclass="math inline">\(I \subseteq\{1, \ldots, m\}\)</span>使得<spanclass="math inline">\(\sum_{j \in I} w_j\)</span>最小。</p></li><li><p><strong>special case:</strong>当<spanclass="math inline">\(w_j=1\)</span>时,称为unweighted set coverproblem.</p></li></ul></li><li><p><strong>问题的推广:vertex cover problem</strong></p></li><li><p><strong>问题的整数规划形式:</strong> <spanclass="math display">\[\begin{aligned}& \operatorname{minimize} \sum_{j=1}^m w_j x_j \\& \text { subject to } \sum_{j: e_i \in S_j} x_j \geq 1, \quad \\& x_j \in\{0,1\}, \quad j=1, \ldots, n,\end{aligned}\]</span></p><ul><li>整数规划最优解对应的目标值:<span class="math inline">\(Z_{IP}^*\)</span>,<span class="math inline">\(Z_{IP}^*=\mathrm{OPT}\)</span></li><li>整数规划无法在多项式时间内求解<ul><li><span class="math inline">\(proof\)</span>:因为set cover问题是<spanclass="math inline">\(NP-hard\)</span>的,假如可以在多项式时间内解决整数规划问题,setcover问题就可以在多项式时间内解决了,矛盾。</li></ul></li><li>但是,线性规划问题是多项式时间内可解的</li></ul></li><li><p><strong>问题的线性规划形式:</strong> <spanclass="math display">\[\begin{aligned}& \operatorname{minimize} \sum_{j=1}^m w_j x_j \\& \text { subject to } \sum_{j: e_i \in S_j} x_j \geq 1, \quad i=1,\ldots, n, \\& x_j \geq 0, \quad j=1, \ldots, m .\end{aligned}\]</span></p></li><li><ul><li>增加约束<span class="math inline">\(x_j \leq1\)</span>是冗余的,因为在问题的任何最优解中,我们可以在不影响解的可行性和不增加其成本的情况下将任意<spanclass="math inline">\(x_j > 1\)</span>减少到<spanclass="math inline">\(x_j = 1\)</span></li><li>因为此问题的线性规划是整数规划的松弛,所以该问题整性规划的解均满足线性规划,且该解在两个模型中具有相等的目标值</li><li>线性规划最优解对应的目标值:<span class="math inline">\(Z_{LP}^*\)</span>,<span class="math inline">\(Z_{I D}^* \leq Z_{ID}^*=\mathrm{OPT}\)</span></li></ul></li></ul><h1 id="vertex-cover-problem">vertex cover problem</h1><ul><li><p><strong>Definition</strong></p><ul><li><p><strong>Input:</strong></p><p>无向图<span class="math inline">\(G=(V,E)\)</span></p><p>任意点<span class="math inline">\(i \in V\)</span>的权值<spanclass="math inline">\(w_i \geq 0\)</span></p></li><li><p><strong>Goal:</strong>寻找一个子集<span class="math inline">\(C\subseteq V\)</span>,满足对任意<span class="math inline">\((i, j) \inE\)</span>,<span class="math inline">\(i \in C\)</span> 或 <spanclass="math inline">\(j \in C\)</span>。</p></li><li><p><strong>special case:</strong>当每个点<spanclass="math inline">\(w_i=1\)</span>时,称为unweighted set coverproblem.</p></li></ul></li></ul><h1 id="algorithm-for-set-cover-problem1lp-rounding">algorithm for setcover problem(1):LP-rounding</h1><ul><li><p><strong>算法:</strong></p><ul><li>由set cover问题的线性规划模型得到最优解<spanclass="math inline">\(x^*\)</span></li><li>对于集合<span class="math inline">\(E\)</span>中的任意<spanclass="math inline">\(e_i(i=1,...,n)\)</span>,<spanclass="math inline">\(f_i=\left|\left\{j: e_i \inS_j\right\}\right|\)</span>,令<span class="math inline">\(f=\max _{i=1,\ldots, n} f_i\)</span>。</li><li>对<span class="math inline">\(x^*\)</span>进行四舍五入,若<spanclass="math inline">\(x_j^* \geq 1 / f\)</span>令<spanclass="math inline">\(\hat{x}_j=1\)</span>,否则令<spanclass="math inline">\(\hat{x}_j=0\)</span>。</li></ul></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230214000356879.png" /></p><ul><li><span class="math inline">\(proof.\)</span>已知<spanclass="math inline">\(x^*\)</span>是线性规划模型的可行解,对于每个<spanclass="math inline">\(e_i\)</span>均满足<spanclass="math inline">\(\sum_{j: e_i \in S_j} x_j^* \geq1\)</span>,即<spanclass="math inline">\(E\)</span>中的每个元素均被覆盖。又由于<spanclass="math inline">\(f_i\)</span>、<spanclass="math inline">\(f\)</span>的定义,<spanclass="math inline">\(e_i\)</span>最终被覆盖的次数最多为<spanclass="math inline">\(f_i\leqf\)</span>,因此每次覆盖的可能性至少为<spanclass="math inline">\(1/f\)</span>。所以对于覆盖<spanclass="math inline">\(e_i\)</span>的<spanclass="math inline">\(S_j\)</span>满足<span class="math inline">\(x_j^*\geq 1 / f\)</span>。综上线性规划模型的最优解<spanclass="math inline">\(x^*\)</span>对应的集合是<spanclass="math inline">\(E\)</span>的覆盖集。</li></ul></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230214000535877.png" /></p><ul><li><p><span class="math inline">\(proof.\)</span></p><ul><li><p>由<span class="math inline">\(Lemma1.5\)</span>的证明可知,对于每个<span class="math inline">\(j\inI\)</span>满足<span class="math inline">\(x_j^* \geq 1 /f\)</span>,所以有<span class="math inline">\(f w_jx_j^*\geq0(j=1,...,m)\)</span>。</p></li><li><p><span class="math display">\[\begin{aligned}\sum_{j \in I} w_j & \leq \sum_{j=1}^m w_j \cdot\left(f \cdotx_j^*\right) \\& =f \sum_{j=1}^m w_j x_j^* \\& =f \cdot Z_{L P}^* \\& \leq f \cdot \mathrm{OPT}\end{aligned}\]</span></p></li></ul></li></ul></li><li><p><strong>special case:</strong>在vertexcover问题中,因为一个点会被两条边所覆盖,满足对<spanclass="math inline">\(\forall i \inV,f_i=2\)</span>。该问题的rounding算法的近似比为2.</p></li></ul><h1 id="algorithm-for-set-cover-problem2dual--rounding">algorithm forset cover problem(2):dual--rounding</h1><ul><li><p><strong>set cover问题中线性规划松弛的对偶线性规划:</strong></p><ul><li><p>假设每个元素<spanclass="math inline">\(e_i\)</span>被一个集合覆盖的代价<spanclass="math inline">\(y_i\geq0\)</span>,设定被高权重集合覆盖的元素价值高,被低权重集合覆盖的元素价值低</p></li><li><p>被同一集合覆盖的元素之和不能高于集合的权重,即<spanclass="math inline">\(\sum_{i: e_i \in S_j} y_i \leqw_j\)</span></p></li><li><p>可以通过下面的线性规划找到元素可以被收取的最高总价</p></li><li><p><span class="math display">\[\begin{array}{ll}\operatorname{maximize} & \sum_{i=1}^n y_i \\\text { subject to } & \sum_{i: e_i \in S_j} y_i \leq w_j, \quadj=1, \ldots, m, \\y_i \geq 0, & i=1, \ldots, n .\end{array}\]</span></p></li><li><p>模型(4)为setcover问题中线性规划松弛的<strong>对偶线性规划</strong>,(3)为(4)的原始线性规划</p></li></ul></li><li><p><strong>set cover问题对偶线性规划的弱对偶性质(weak dualityproperty):</strong></p><ul><li><span class="math inline">\(\sum_{i=1}^n y_i \leq \sum_{i=1}^n y_i\sum_{j: e_i \in S_j} x_j\)</span><ul><li>因为<span class="math inline">\(\sum_{j: e_i \in S_j} x_j \geq1\)</span></li></ul></li><li>又因为不等式右边可以改写为<span class="math inline">\(\sum_{i=1}^ny_i \sum_{j: e_i \in S_j} x_j=\sum_{j=1}^m x_j \sum_{i: e_i \in S_j}y_i\)</span><ul><li>左边为所有<spanclass="math inline">\(e_i\)</span>的价值乘以它所在<spanclass="math inline">\(S_j\)</span>的个数,右边先求属于同一<spanclass="math inline">\(S_j\)</span>的<spanclass="math inline">\(e_i\)</span>的价值和,在对所有的<spanclass="math inline">\(S_j\)</span>求和。</li></ul></li><li>因为<spanclass="math inline">\(y\)</span>是对偶线性规划的可行解,所以<spanclass="math inline">\(\sum_{j=1}^m x_j \sum_{i: e_i \in S_j} y_i \leq\sum_{j=1}^m x_j w_j\)</span><ul><li>因为<span class="math inline">\(\sum_{i: e_i \in S_j} y_i \leqw_j\)</span></li></ul></li><li>综上,<span class="math inline">\(\sum_{i=1}^n y_i \leq \sum_{j=1}^mw_j x_j\)</span></li><li>也就是说,<strong>任意对偶问题线性规划可行解的目标值小于等于任意原线性规划问题可行解的目标值</strong>,即<spanclass="math inline">\(\sum_{i=1}^n y_i \leq Z_{LP}^*\)</span>。<strong>这被称为线性规划的弱对偶性质。</strong></li><li>又因为<span class="math inline">\(Z_{L P}^* \leq\mathrm{OPT}\)</span>,可得<span class="math inline">\(\sum_{i=1}^n y_i\leq \mathrm{OPT}\)</span>。</li></ul></li><li><p><strong>set cover问题对偶线性规划的强对偶性质(strong dualityproperty):</strong></p><ul><li><strong>强对偶性质:只要原始线性规划和对偶线性规划都存在可行解,那么它们的最优值相等。</strong></li><li><spanclass="math inline">\(x^*\)</span>是原线性规划问题的最优解,<spanclass="math inline">\(y^*\)</span>是对偶线性规划的最优解,则</li><li><span class="math inline">\(\sum_{j=1}^m w_j x_j^*=\sum_{i=1}^ny_i^*\)</span></li></ul></li><li><p><strong>算法:</strong></p><ul><li><p>选择所有使得对偶线性规划模型约束是紧的<spanclass="math inline">\(S_j\)</span>,即所有的<spanclass="math inline">\(S_j\)</span>满足<spanclass="math inline">\(\sum_{i: e_i \in S_j}y_i^*=w_j\)</span>。这是一个<spanclass="math inline">\(f-\)</span>近似的近似算法。</p></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230214222356266.png" /></p><ul><li><p><span class="math inline">\(proof.\)</span></p><ul><li><p><span class="math inline">\(idea\)</span>:先假设有元素<spanclass="math inline">\(e_k\)</span>没有被<spanclass="math inline">\(y^*\)</span>对应的集合覆盖,在<spanclass="math inline">\(y^*\)</span>的基础上构造新的覆盖集<spanclass="math inline">\(y'\)</span>,<spanclass="math inline">\(y'\)</span>是满足对偶约束、目标值更优的覆盖集,矛盾。</p></li><li><p>假设存在没有被覆盖的元素<spanclass="math inline">\(e_k\)</span>,则对任意覆盖<spanclass="math inline">\(e_k\)</span>的集合<spanclass="math inline">\(S_j\)</span>,有<spanclass="math inline">\(\sum_{i: e_i \in S_j}y_i^*<w_j\)</span>。令<span class="math inline">\(\epsilon=\min _{j:e_i \in S_j}\left(w_j-\sum_{i: e_i \in S_j}y_i^*\right)\)</span>,由前面的不等式可知,<spanclass="math inline">\(\epsilon>0\)</span></p></li><li><p>考虑一个新的对偶解<spanclass="math inline">\(y'\)</span>,其中<spanclass="math inline">\(y_k'=y_k^*+\epsilon\)</span>,<spanclass="math inline">\(y'\)</span>的剩余部分同<spanclass="math inline">\(y^*\)</span>。<spanclass="math inline">\(y'\)</span>是对偶可行解,因为对任意包含<spanclass="math inline">\(e_k\)</span>的<spanclass="math inline">\(S_j\)</span>,有<spanclass="math inline">\(\sum_{i: e_i \in S_j} y_i^{\prime}=\sum_{i: e_i\in S_j} y_i^*+\epsilon \leq w_j\)</span>。</p></li><li><p>由<spanclass="math inline">\(\epsilon\)</span>的定义,对于任意不包含<spanclass="math inline">\(e_k\)</span>的<spanclass="math inline">\(S_j\)</span>,<span class="math inline">\(\sum_{i:e_i \in S_j} y_i^{\prime}=\sum_{i: e_i \in S_j} y_i^* \leqw_j\)</span>。</p></li><li><p>又因为<span class="math inline">\(\sum_{i=1}^ny_i^{\prime}>\sum_{i=1}^n y_i^*\)</span>,这与<spanclass="math inline">\(y^*\)</span>的最优性相悖。</p></li><li><p>综上,所有元素都被覆盖且<spanclass="math inline">\(I'\)</span>是集合覆盖。</p></li></ul></li></ul></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230214222448527.png" /></p><ul><li><p><span class="math inline">\(proof.\)</span></p><ul><li><p><span class="math inline">\(idea.\)</span><strong>"charging"argument:</strong>当我们选择一个集合<spanclass="math inline">\(S_j\)</span>作为覆盖集合时,通过向它的每个元素"charging"<spanclass="math inline">\(y_i^*\)</span>来进行付费;对于每个包含<spanclass="math inline">\(e_i\)</span>的集合,每个元素最多被付费一次,因此总成本最多为<spanclass="math inline">\(f \sum_{i=1}^my_i^*\)</span>,或者是对偶目标函数的<spanclass="math inline">\(f\)</span>倍。</p></li><li><p>由于该算法得到的覆盖<span class="math inline">\(j\inI'\)</span>均满足<span class="math inline">\(w_j=\sum_{i: e_i \inS_j} y_i^*\)</span>。</p></li><li><p>则覆盖集的总价值</p></li><li><p><span class="math display">\[\begin{aligned}\sum_{j \in I^{\prime}} w_j & =\sum_{j \in I^{\prime}} \sum_{i: e_i\in S_j} y_i^* \\& =\sum_{i=1}^n\left|\left\{j \in I^{\prime}: e_i \inS_j\right\}\right| \cdot y_i^* \\& \leq \sum_{i=1}^n f_i y_i^* \\& \leq f \sum_{i=1}^n y_i^* \\& \leq f \cdot \mathrm{OPT} .\end{aligned}\]</span></p></li></ul></li></ul></li></ul></li><li><p>比较<span class="math inline">\(LP-rounding\)</span>与<spanclass="math inline">\(dual-rounding\)</span>算法:</p><ul><li>设由<spanclass="math inline">\(LP-rounding\)</span>算法得到的集合下标为<spanclass="math inline">\(I\)</span>,<spanclass="math inline">\(dual-rounding\)</span>算法得到的集合下标为<spanclass="math inline">\(I’\)</span>,有<span class="math inline">\(I\subseteq I^{\prime}\)</span>。</li><li><strong>互补松弛性(complementary slackness)</strong>:<ul><li>由前面的弱对偶性:<span class="math inline">\(\sum_{i=1}^n y_i \leq\sum_{i=1}^n y_i \sum_{j: e_i \in S_j} x_j=\sum_{j=1}^m x_j \sum_{i: e_i\in S_j} y_i \leq \sum_{j=1}^m x_j w_j\)</span></li><li>又因为强对偶性表明,对于最优解<spanclass="math inline">\(x^*\)</span>与<spanclass="math inline">\(y^*\)</span>:<spanclass="math inline">\(\sum_{i=1}^n y_i^*=\sum_{j=1}^m w_jx_j^*\)</span>。只有<spanclass="math inline">\(y_i^*>0\)</span>,<spanclass="math inline">\(\sum_{j: e_i \in S_j} x_j^*=1\)</span>;<spanclass="math inline">\(x_j^*>0\)</span>,<spanclass="math inline">\(\sum_{i: e_i \in S_j}y_i^*=w_j\)</span>时满足这种情况。</li><li><strong>1.互补松弛条件:</strong>每当线性规划变量(原始或对偶)非零时,对应的对偶或原始约束是紧的。</li><li><strong>2.</strong>如果<spanclass="math inline">\(x^*\)</span>和<spanclass="math inline">\(y^*\)</span>是最优解,互补松弛条件必须成立。反之亦然,如果<spanclass="math inline">\(x^*\)</span>和<spanclass="math inline">\(y^*\)</span>分别是可行的原始解和对偶解,那么如果互补松弛条件成立,则两个目标函数的值相等,此解一定是最优的。</li></ul></li><li>如果对于任意的原始最优解<spanclass="math inline">\(x^*\)</span>,都有<spanclass="math inline">\(x_j^* >0\)</span>,那么对于任意的对偶最优解<spanclass="math inline">\(y^*\)</span>,对应的关于<spanclass="math inline">\(S_j\)</span>的对偶不等式一定是紧的。回想上一节的算法,当<spanclass="math inline">\(x_j^ *\geq1 / f\)</span>时,令<spanclass="math inline">\(j\in I\)</span>。因此<spanclass="math inline">\(j\in I\)</span>意味着<spanclass="math inline">\(j\in I'\)</span>,从而<spanclass="math inline">\(I'\subseteq I\)</span>。</li><li>综上,<span class="math inline">\(I'= I\)</span>。</li></ul></li></ul><h1 id="algorithm-for-set-cover-problem3primal-dual-algorithm">algorithmfor set cover problem(3):primal-dual algorithm</h1><ul><li><p>前两节算法的一个缺点是<strong>需要求解一个线性规划</strong>。虽然线性程序是高效可解的,并且其算法在实际应用中是快速的,但是<strong>特殊目的的算法往往要快得多</strong>。</p></li><li><p><strong>最优对偶解的性质</strong></p></li><li><p><strong>原始-对偶优化算法:</strong>线性规划问题、网络流问题、最短路径问题等都有原-对偶优化算法。<strong>原始-对偶算法从一个对偶可行解开始,利用对偶信息来推断一个原始的、可能不可行的解。如果原始解确实不可行,则修改对偶解以增加对偶目标函数的值。</strong></p></li><li><p><strong>算法:</strong></p><ul><li><p><spanclass="math inline">\(idea.\)</span>构造对偶解而不是求解对偶<spanclass="math inline">\(LP\)</span>。</p></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230215132648220.png" /></p><ul><li><p><strong>step1:</strong>给出一个初始对偶可行解<spanclass="math inline">\(y=0\)</span>,此时<spanclass="math inline">\(I\)</span>为空集。</p></li><li><p><strong>step2:</strong>进行最多<spanclass="math inline">\(n\)</span>次循环,在每次循环中假如存在不被覆盖的元素<spanclass="math inline">\(e_i\)</span>,增加对应的变量<spanclass="math inline">\(y_i\)</span>直到引入覆盖<spanclass="math inline">\(e_i\)</span>的<spanclass="math inline">\(S_l\)</span>,满足<spanclass="math inline">\(\sum_{j: e_j \in S_{\ell}}y_j=w_{\ell}\)</span>。</p></li><li><p><strong>step3:</strong>在每次循环结束后<spanclass="math inline">\(I \leftarrow I\cup\{\ell\}\)</span>,进入下一次循环。</p></li></ul></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230215132748034.png" /></p><ul><li>同<span class="math inline">\(dual-rounding\)</span>算法。</li></ul></li></ul></li></ul><h1 id="algorithm-for-set-cover-problem4a-greedy-algorithm">algorithmfor set cover problem(4):A greedy algorithm</h1><ul><li><p><strong>算法:</strong></p><ul><li><p><span class="math inline">\(idea:\)</span>每一轮选择一个新的集合,直到所有元素被覆盖。</p></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230215183851851.png" /></p><ul><li><strong>step1:</strong>初始化<spanclass="math inline">\(I\)</span>为空集,对任意<spanclass="math inline">\(j\)</span>,<span class="math inline">\(\hat{S}_j\leftarrow S_j\)</span></li><li><strong>step2:</strong>进行若干次循环,直到<spanclass="math inline">\(I\)</span>对应的集合是<spanclass="math inline">\(E\)</span>的覆盖</li><li><strong>step3:</strong>在每次循环中,选取<strong>权重与其包含的当前未覆盖元素个数之比最小</strong>的集合,将该集合的下标并入<spanclass="math inline">\(I\)</span>。对所有<spanclass="math inline">\(\hat{S}_j\)</span>去掉已经被覆盖的元素。进入下一次循环。</li></ul></li><li><p><strong>时间复杂度:</strong><spanclass="math inline">\(O(m^2)\)</span></p></li></ul></li><li><p><strong>notation and a useful mathematical fact:</strong></p><ul><li><strong><span class="math inline">\(k\)</span>次调和数<spanclass="math inline">\(H_k\)</span>(kth harmonic number):</strong><ul><li><spanclass="math inline">\(H_k=1+\frac{1}{2}+\frac{1}{3}+\cdots+\frac{1}{k}\)</span></li><li><span class="math inline">\(H_k \approx \ln k\)</span></li></ul></li><li><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230215191023131.png" /></li></ul></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230215191330112.png" /></p><ul><li><p><span class="math inline">\(proof.\)</span></p><ul><li><p>令<span class="math inline">\(n_k\)</span>表示第<spanclass="math inline">\(k\)</span>次迭代开始时剩余未覆盖的元素个数。假如算法总共进行了<spanclass="math inline">\(\ell\)</span>次迭代,则<spanclass="math inline">\(n_1=n\)</span>,<spanclass="math inline">\(n_{l+1}=0\)</span>。</p></li><li><p>选择任意次迭代<span class="math inline">\(k\)</span>,令<spanclass="math inline">\(I_k\)</span>表示迭代<spanclass="math inline">\(1\)</span>到<span class="math inline">\(k -1\)</span>中所选集合的下标。</p></li><li><p>对任意<span class="math inline">\(j=1,...,m\)</span>,令<spanclass="math inline">\(\hat{S}_j\)</span>表示迭代开始时<spanclass="math inline">\(S_j\)</span>中未覆盖元素的集合,<spanclass="math inline">\(\hat{S}_j=S_j-\bigcup_{p \in I_k}S_p\)</span></p></li><li><p>对于在<spanclass="math inline">\(k\)</span>次迭代中选择的集合<spanclass="math inline">\(j\)</span>,满足<span class="math inline">\(w_j\leq \frac{n_k-n_{k+1}}{n_k} \mathrm{OPT}\)</span></p><ul><li>设<spanclass="math inline">\(O\)</span>包含最优解中集合的指标,则在第<spanclass="math inline">\(k\)</span>次迭代中满足<spanclass="math inline">\(\min _{j: \hat{S}_j \neq \emptyset}\frac{w_j}{\left|\hat{S}_j\right|} \leq \frac{\sum_{j \in O}w_j}{\sum_{j \in O}\left|\hat{S}_j\right|}=\frac{\mathrm{OPT}}{\sum_{j\in O}\left|\hat{S}_j\right|} \leq \frac{\mathrm{OPT}}{n_k}\)</span><ul><li>第一个不等式是因为Fact 1.10</li><li>最后一个不等式是因为<span class="math inline">\(U_{j \in O}\hat{S}_j\)</span>必须包含着剩余<spanclass="math inline">\(n_k\)</span>个没被覆盖的元素,所以<spanclass="math inline">\(\sum_{j \in O}\left|\hat{S}_j\right|\geqn_k\)</span></li></ul></li><li>又因为<spanclass="math inline">\(n_{k+1}=n_k-\left|\hat{S}_j\right|\)</span>,所以<spanclass="math inline">\(w_j \leq \frac{\left|\hat{S}_j\right|\mathrm{OPT}}{n_k}=\frac{n_k-n_{k+1}}{n_k} \mathrm{OPT}\)</span></li></ul></li><li><p><span class="math display">\[\begin{aligned}\sum_{j \in I} w_j & \leq \sum_{k=1}^{\ell} \frac{n_k-n_{k+1}}{n_k}\mathrm{OPT} \\& \leq \mathrm{OPT} \cdot\sum_{k=1}^{\ell}\left(\frac{1}{n_k}+\frac{1}{n_k-1}+\cdots+\frac{1}{n_{k+1}+1}\right)\\& =\mathrm{OPT} \cdot \sum_{i=1}^n \frac{1}{i} \\& =H_n \cdot \mathrm{OPT}\end{aligned}\]</span></p><ul><li><p>第二个不等式是因为<span class="math inline">\(\frac{1}{n_k} \leq\frac{1}{n_k-i}\)</span></p></li><li><p><span class="math display">\[\begin{aligned}\frac{n_k-n_{k+1}}{n_k}&=\frac{1}{n_k}*(n_k-n_{k+1})\\&=\frac{1}{n_k}+\frac{1}{n_k}+\cdots+\frac{1}{n_{k}}\\&\leq\frac{1}{n_k}+\frac{1}{n_k-1}+\cdots+\frac{1}{n_{k+1}+1}\end{aligned}\]</span></p></li></ul></li></ul></li></ul></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230215200149867.png" /></p><ul><li><p><strong>对比<spanclass="math inline">\(greedy-algorithm\)</span>和$LP-rounding$</strong></p></li><li><p><span class="math inline">\(proof.\)</span></p><ul><li><p><span class="math inline">\(idea.\)</span>构造对偶拟合</p></li><li><p><strong>对偶拟合(dualfitting)</strong>:构造一个不可行对偶解,<strong>这个解的目标值与原始解的值相等</strong>,对对偶解进行单值放缩使之具有可行性。</p></li><li><p><strong>step1:构造不可行对偶解。</strong></p><ul><li>假设在第<span class="math inline">\(k\)</span>次迭代中加入集合<spanclass="math inline">\(S_j\)</span>,对任意在此次迭代之前没被覆盖的元素<spanclass="math inline">\(e_i \in \hat{S}_j\)</span>,令<spanclass="math inline">\(y_i=w_j /\left|\hat{S}_j\right|\)</span>。<spanclass="math inline">\(w_j=\sum_{i: e_i \in \hat{S}_j}y_i\)</span>,因为在第<spanclass="math inline">\(k\)</span>次迭代中选择的子集<spanclass="math inline">\(S_j\)</span>的权重等于在第<spanclass="math inline">\(k\)</span>次迭代中覆盖的未覆盖元素的对偶<spanclass="math inline">\(y_i\)</span>之和,因此<spanclass="math inline">\(\sum_{j \in I} w_j=\sum_{i=1}^ny_i\)</span>。</li></ul></li><li><p><strong>step2:对不可行对偶解进行放缩,得到可行对偶解(证明<spanclass="math inline">\(y^{\prime}=\frac{1}{H_g}y\)</span>可行)</strong></p><ul><li><p>证明<span class="math inline">\(y^{\prime}=\frac{1}{H_g}y\)</span>可行,即证明对任意的<spanclass="math inline">\(S_j\)</span>有<span class="math inline">\(\sum_{i:e_i \in S_j} y_i^{\prime} \leq w_j\)</span>。</p></li><li><p>令<span class="math inline">\(a_k\)</span>为第<spanclass="math inline">\(k\)</span>次迭代开始前仍未被覆盖的元素个数,其中<spanclass="math inline">\(a_1=\left|S_j\right|\)</span>,<spanclass="math inline">\(a_{\ell+1}=0\)</span>。令<spanclass="math inline">\(A_k\)</span>为经过第<spanclass="math inline">\(k\)</span>次迭代后被新覆盖的元素个数,<spanclass="math inline">\(\left|A_k\right|=a_k-a_{k+1}\)</span>。假如<spanclass="math inline">\(S_p\)</span>是第<spanclass="math inline">\(k\)</span>次迭代被加入的集合,则对任意<spanclass="math inline">\(e_i \in A_k\)</span>,有<spanclass="math inline">\(y_i^{\prime}=\frac{w_p}{H_g\left|\hat{S}_p\right|}\leq \frac{w_j}{H_g a_k}\)</span></p><ul><li><span class="math inline">\(\hat{S}_p\)</span>为第<spanclass="math inline">\(k\)</span>次迭代开始前<spanclass="math inline">\(S_p\)</span>包含的没被覆盖的元素,<spanclass="math inline">\(S_p\)</span>之所以被选中是因为它的权重与它所包含的未覆盖元素个数的比值最小。</li></ul></li><li><p><span class="math display">\[\begin{aligned}\sum_{i: e_i \in S_j} y_i^{\prime} & =\sum_{k=1}^{\ell} \sum_{i: e_i\in A_k} y_i^{\prime} \\& \leq \sum_{k=1}^{\ell}\left(a_k-a_{k+1}\right) \frac{w_j}{H_g a_k}\\& \leq \frac{w_j}{H_g} \sum_{k=1}^{\ell} \frac{a_k-a_{k+1}}{a_k} \\& \leq \frac{w_j}{H_g}\sum_{k=1}^{\ell}\left(\frac{1}{a_k}+\frac{1}{a_k-1}+\cdots+\frac{1}{a_{k+1}+1}\right)\\& \leq \frac{w_j}{H_g} \sum_{i=1}^{\left|S_j\right|} \frac{1}{i} \\& =\frac{w_j}{H_g} H_{\left|S_j\right|} \\& \leq w_j\end{aligned}\]</span></p><ul><li>其中,<span class="math inline">\(g=\max_j\left|S_j\right|\)</span>,显然<spanclass="math inline">\(H_{\left|S_j\right|} \leq H_g\)</span></li></ul></li></ul></li></ul></li></ul></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230215200341492.png" /></p></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230215200358132.png" /></p></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230215200424819.png" /></p></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230215200440921.png" /></p></li></ul><h1id="algorithm-for-set-cover-problem5a-randomized-rounding-algorithm">algorithmfor set cover problem(5):A randomized rounding algorithm</h1><ul><li><p>在本节中,我们考虑了一种设计集合覆盖问题近似算法的最终技术。尽管该算法<strong>比上一节的贪婪算法更慢,也没有更好的保证</strong>,但我们将其包括在这里,因为它引入了<strong>在近似算法中使用随机化的概念</strong>,我们将在第五章中深入讨论这个想法。</p></li><li><p><strong>算法:</strong></p><ul><li><p>对setcover问题求解一个线性规划松弛,然后将分式解<strong>随机舍入</strong>为整数解。</p></li><li><p><strong>随机舍入:</strong></p><ul><li><p>设<span class="math inline">\(x^*\)</span>为<spanclass="math inline">\(LP\)</span>松弛的最优解,希望将<spanclass="math inline">\(x^*\)</span>取整为1或者0,从而在不增加过多成本的情况下,得到setcover问题的整数规划形式的解<spanclass="math inline">\(\hat{x}\)</span>。</p></li><li><p><span class="math inline">\(x_j^*\)</span>为将<spanclass="math inline">\(\hat{x}_j\)</span>设为1的概率,因此每个子集<spanclass="math inline">\(S_j\)</span>以概率<spanclass="math inline">\(x_j^*\)</span>包含在我们的解中,其中<spanclass="math inline">\(m\)</span>个事件( <spanclass="math inline">\(S_j\)</span>包含在我们的解中)是独立的随机事件。</p></li><li><p>设<spanclass="math inline">\(X_j\)</span>是一个随机变量,如果子集<spanclass="math inline">\(S_j\)</span>包含在解中,则<spanclass="math inline">\(X_j\)</span>为1,否则为0。<spanclass="math inline">\(E\left[\sum_{j=1}^m w_j X_j\right]=\sum_{j=1}^mw_j \operatorname{Pr}\left[X_j=1\right]=\sum_{j=1}^m w_j x_j^*=Z_{LP}^*\)</span></p></li><li><p>由随机舍入得到的集合既有可能是覆盖,也有可能不是。计算给定元素<spanclass="math inline">\(e_i\)</span>不被这个过程覆盖的概率,即包含<spanclass="math inline">\(e_i\)</span>的子集中没有一个包含在解中的概率,为<spanclass="math inline">\(\prod_{j: e_i \inS_j}\left(1-x_j^*\right)\)</span>。</p></li><li><p><span class="math display">\[\begin{aligned}\operatorname{Pr}\left[e_i \text { not covered }\right] & =\prod_{j:e_i \in S_j}\left(1-x_j^*\right) \\& \leq \prod_{j: e_i \in S_j} e^{-x_j^*} \\& =e^{-\sum_{j: e_i \in S_j} x_j^*} \\& \leq e^{-1}\end{aligned}\]</span></p><ul><li>第一的不等式是因为<span class="math inline">\(1-x \leqe^{-x}\)</span></li><li>最后一个不等式是因为在<spanclass="math inline">\(LP\)</span>模型中<spanclass="math inline">\(\sum_{j: e_i \in S_j} x_j^* \geq 1\)</span>。</li></ul></li><li><p>因此<strong>在最坏的情况下,这种随机取整过程很可能不会产生集合覆盖。</strong></p></li></ul></li><li><p><strong>什么叫高概率工作的算法?</strong></p><ul><li>假设对于任意常数<spanclass="math inline">\(c\)</span>,我们可以设计一个多项式时间算法,其失败的概率至多是一个逆多项式<spanclass="math inline">\(n^{-c}\)</span>,然后我们说我们有一个高概率工作的算法。</li></ul></li><li><p><strong>如何设计出一个更有可能产生集合覆盖的算法?</strong></p><ul><li>如果我们能够<strong>设计一个随机过程</strong>使得对于某个常数<spanclass="math inline">\(c\geq2\)</span>,<spanclass="math inline">\(\operatorname{Pr}\left[e_i\right.\)</span> notcovered <span class="math inline">\(] \leq \frac{1}{n^c}\)</span></li><li>那么<span class="math inline">\(\operatorname{Pr}[\)</span> thereexists an uncovered element <span class="math inline">\(] \leq\sum_{i=1}^n \operatorname{Pr}\left[e_i\right.\)</span> not covered<span class="math inline">\(] \leq \frac{1}{n^{c-1}}\)</span></li><li>结合上一部分可以称这个算法会有一个高概率的集合覆盖。</li></ul></li><li><p><strong>如何达到<spanclass="math inline">\(n^{-c}\)</span>的界?</strong></p><ul><li><p>对于任意的集合<spanclass="math inline">\(S_j\)</span>,假设一个硬币以<spanclass="math inline">\(x^*_j\)</span>的概率正面朝上,将硬币抛<spanclass="math inline">\(clnn\)</span>次,如果硬币在任意一次正面朝上,则将<spanclass="math inline">\(S_j\)</span>包含在解中。可以发现<spanclass="math inline">\(S_j\)</span>不被包含在解中的概率为<spanclass="math inline">\(\left(1-x_j^*\right)^{c \ln n}\)</span>。</p></li><li><p>此时</p></li><li><p><span class="math display">\[\begin{aligned}\operatorname{Pr}\left[e_i \text { not covered }\right] & =\prod_{j:e_i \in S_j}\left(1-x_j^*\right)^{c \ln n} \\& \leq \prod_{j: e_i \in S_j} e^{-x_j^*(c \ln n)} \\& =e^{-(c \ln n) \sum_{j: e_i \in S_j} x_j^*} \\& \leq \frac{1}{n^c}\end{aligned}\]</span></p></li></ul></li></ul></li><li><p><imgsrc="../images/An-introduction-to-approximation-algorithms/image-20230216183518422.png" /></p><ul><li><p>证明该算法在产生集合覆盖的情况下具有良好的期望值</p></li><li><p><span class="math inline">\(proof.\)</span></p><ul><li><p><strong>step1:计算期望</strong></p></li><li><p><span class="math inline">\(p_j\left(x_j^*\right)\)</span>是<spanclass="math inline">\(x_j^*\)</span>的函数,是将集合<spanclass="math inline">\(S_j\)</span>包含在解中的概率。<spanclass="math inline">\(p_j\left(x_j^*\right)=1-\left(1-x_j^*\right)^{c\ln n}\)</span>。若<span class="math inline">\(x_j^*\in[0,1]\)</span>且<span class="math inline">\(c \ln n \geq1\)</span>,则得到导数<spanclass="math inline">\(p_j^{\prime}\left(x_j^*\right)=(c \lnn)\left(1-x_j^*\right)^{(c \ln n)-1} \leq(c \ln n)\)</span>。</p></li><li><p>因为<span class="math inline">\(p_j(0)=0\)</span>,且函数<spanclass="math inline">\(p_j\)</span>的斜率在区间<spanclass="math inline">\([0,1]\)</span>上方以<span class="math inline">\(c\ln n\)</span>为界,所以在区间<spanclass="math inline">\([0,1]\)</span>上<spanclass="math inline">\(p_j\left(x_j^*\right) \leq(c \ln n)x_j^*\)</span>。设<spanclass="math inline">\(X_j\)</span>是一个随机变量,如果子集<spanclass="math inline">\(S_j\)</span>包含在解中,则<spanclass="math inline">\(X_j\)</span>为1,否则为0。则,</p></li><li><p><span class="math display">\[\begin{aligned}E\left[\sum_{j=1}^m w_j X_j\right] & =\sum_{j=1}^m w_j\operatorname{Pr}\left[X_j=1\right] \\& \leq \sum_{j=1}^m w_j(c \ln n) x_j^* \\& =(c \ln n) \sum_{j=1}^m w_j x_j^*=(c \ln n) Z_{L P}^*\end{aligned}\]</span></p></li><li><p><strong>step2:在给定集合覆盖产生的情况下,约束解的期望值</strong></p></li><li><p>设<spanclass="math inline">\(F\)</span>是由随机过程得到的解是可行覆盖集的事件,<spanclass="math inline">\(\bar{F}\)</span>是这个事件的补集.由前面的讨论知道<spanclass="math inline">\(\operatorname{Pr}[F] \geq1-\frac{1}{n^{c-1}}\)</span>。</p></li><li><p><span class="math display">\[E\left[\sum_{j=1}^m w_j X_j\right]=E\left[\sum_{j=1}^m w_j X_j \midF\right] \operatorname{Pr}[F]+E\left[\sum_{j=1}^m w_j X_j \mid\bar{F}\right] \operatorname{Pr}[\bar{F}]\]</span></p></li><li><p>因为<span class="math inline">\(w_j\geq0\)</span>,且<spanclass="math inline">\(E\left[\sum_{j=1}^m w_j X_j \mid \bar{F}\right]\geq 0\)</span></p></li><li><p>所以当<span class="math inline">\(n\geq2\)</span>且<spanclass="math inline">\(c\geq2\)</span>时</p></li><li><p><span class="math display">\[\begin{aligned}E\left[\sum_{j=1}^m w_j X_j \mid F\right] &=\frac{1}{\operatorname{Pr}[F]}\left(E\left[\sum_{j=1}^m w_jX_j\right]-E\left[\sum_{j=1}^m w_j X_j \mid \bar{F}\right]\operatorname{Pr}[\bar{F}]\right) \\& \leq \frac{1}{\operatorname{Pr}[F]} \cdot E\left[\sum_{j=1}^m w_jX_j\right] \\& \leq \frac{(c \ln n) Z_{L P}^*}{1-\frac{1}{n^{c-1}}} \\& \leq 2 c(\ln n) Z_{L P}^*\end{aligned}\]</span></p></li></ul></li></ul></li></ul>]]></content>
<categories>
<category> 运筹 </category>
<category> 近似算法 </category>
</categories>
<tags>
<tag> 近似算法 </tag>
</tags>
</entry>
<entry>
<title>cpp学习笔记</title>
<link href="/post/a3fa5835.html"/>
<url>/post/a3fa5835.html</url>
<content type="html"><</span><br><span class="line"></span><br><span class="line">* ~~~c++</span><br><span class="line"> //单精度float(4)</span><br><span class="line"> float f1 = 3.14f;</span><br><span class="line"> //双精度double(8)</span><br><span class="line"> double d1 = 3.14;</span><br><span class="line"> cout << "float sizeof = " << sizeof(f1) << endl;</span><br><span class="line"> cout << "double sizeof = " << sizeof(d1) << endl;</span><br></pre></td></tr></table></figure></p></li><li><p><strong>科学计数法</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//科学计数法</span></span><br><span class="line"><span class="type">float</span> f2 = <span class="number">3e2</span>; <span class="comment">// 3 * 10 ^ 2 </span></span><br><span class="line">cout << <span class="string">"f2 = "</span> << f2 << endl;</span><br><span class="line"></span><br><span class="line"><span class="type">float</span> f3 = <span class="number">3e-2</span>; <span class="comment">// 3 * 0.1 ^ 2</span></span><br><span class="line">cout << <span class="string">"f3 = "</span> << f3 << endl;</span><br></pre></td></tr></table></figure></li><li><p><strong>字符型</strong>(单个字符)</p></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//字符型char(1)</span></span><br><span class="line"><span class="type">char</span> ch = <span class="string">'a'</span>;</span><br><span class="line">cout << ch << endl;</span><br><span class="line">cout << <span class="built_in">sizeof</span>(<span class="type">char</span>) << endl;</span><br><span class="line"></span><br><span class="line"><span class="comment">//ch = "abcde"; //错误,不可以用双引号</span></span><br><span class="line"><span class="comment">//ch = 'abcde'; //错误,单引号内只能引用一个字符</span></span><br><span class="line"></span><br><span class="line">cout << (<span class="type">int</span>)ch << endl; <span class="comment">//查看字符a对应的ASCII码</span></span><br><span class="line">ch = <span class="number">97</span>; <span class="comment">//可以直接用ASCII给字符型变量赋值</span></span><br><span class="line">cout << ch << endl;</span><br></pre></td></tr></table></figure><ul><li><strong>转义字符</strong></li></ul><p><imgsrc="../images/cpp%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20230121055248753.png" /></p><ul><li><p><strong>字符串类型</strong></p><ul><li><p>C语言风格<code>char 变量名[] = "字符串值"</code></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//字符串(风格1)</span></span><br><span class="line"><span class="type">char</span> str1[] = <span class="string">"hello world"</span>;</span><br><span class="line">cout << str1 << endl;</span><br><span class="line"><span class="comment">//C风格的字符串要用双引号括起来</span></span><br></pre></td></tr></table></figure></li><li><p>C++风格<code>string 变量名 = "字符串值"</code></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//字符串(风格2)</span></span><br><span class="line">string str = <span class="string">"hello world"</span>;</span><br><span class="line">cout << str << endl;</span><br><span class="line"><span class="comment">//C++风格字符串,需要加入头文件#include<string></span></span><br></pre></td></tr></table></figure></li></ul></li><li><p><strong>布尔类型</strong>(true1 false0)</p></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//布尔型变量</span></span><br><span class="line"><span class="type">bool</span> flag = <span class="literal">true</span>;</span><br><span class="line">cout << flag << endl; <span class="comment">// 1</span></span><br><span class="line"></span><br><span class="line">flag = <span class="literal">false</span>;</span><br><span class="line">cout << flag << endl; <span class="comment">// 0</span></span><br><span class="line"></span><br><span class="line">cout << <span class="string">"size of bool = "</span> << <span class="built_in">sizeof</span>(<span class="type">bool</span>) << endl; <span class="comment">//1</span></span><br></pre></td></tr></table></figure><ul><li><strong>数据输入</strong><code>cin >> 变量</code></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//输入整型</span></span><br><span class="line"><span class="type">int</span> a = <span class="number">0</span>;</span><br><span class="line">cout << <span class="string">"输入a"</span> << endl;</span><br><span class="line">cin >> a;</span><br><span class="line">cout << a << endl;</span><br><span class="line"><span class="comment">//浮点型输入</span></span><br><span class="line"><span class="type">double</span> d = <span class="number">0</span>;</span><br><span class="line">cout << <span class="string">"请输入浮点型变量:"</span> << endl;</span><br><span class="line">cin >> d;</span><br><span class="line">cout << d << endl;</span><br><span class="line"><span class="comment">//字符型输入</span></span><br><span class="line"><span class="type">char</span> ch = <span class="number">0</span>;</span><br><span class="line">cout << <span class="string">"请输入字符型变量:"</span> << endl;</span><br><span class="line">cin >> ch;</span><br><span class="line">cout << ch << endl;</span><br><span class="line"></span><br><span class="line"><span class="comment">//字符串型输入</span></span><br><span class="line">string str;</span><br><span class="line">cout << <span class="string">"请输入字符串型变量:"</span> << endl;</span><br><span class="line">cin >> str;</span><br><span class="line">cout << str << endl;</span><br><span class="line"></span><br><span class="line"><span class="comment">//布尔类型输入</span></span><br><span class="line"><span class="type">bool</span> flag = <span class="literal">true</span>;</span><br><span class="line">cout << <span class="string">"请输入布尔型变量:"</span> << endl;</span><br><span class="line">cin >> flag;</span><br><span class="line">cout << flag << endl;</span><br></pre></td></tr></table></figure><h3 id="运算符">运算符</h3><p><imgsrc="../images/cpp%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20230121070507951.png" /></p><ul><li>算术运算符</li></ul><p><imgsrc="../images/cpp%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20230121072519507.png" /></p><ul><li>赋值运算符</li></ul><p><imgsrc="../images/cpp%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20230121072607892.png" /></p><ul><li>比较运算符</li></ul><p><imgsrc="../images/cpp%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20230121072649204.png" /></p><ul><li>逻辑运算符</li></ul><p><imgsrc="../images/cpp%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20230121072728402.png" /></p><h3 id="程序逻辑控制">程序逻辑控制</h3><h4 id="选择结构">选择结构</h4><ul><li><p><strong>if条件表达式</strong></p></li><li><p><strong>三目运算符</strong><code>表达式1 ? 表达式2 :表达式3</code></p></li><li><p><strong>switch语句</strong></p></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">switch</span>(表达式)</span><br><span class="line"></span><br><span class="line">{</span><br><span class="line"></span><br><span class="line"><span class="keyword">case</span> 结果<span class="number">1</span>:执行语句;<span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">case</span> 结果<span class="number">2</span>:执行语句;<span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="keyword">default</span>:执行语句;<span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="循环结构">循环结构</h4><ul><li><strong>while循环语句</strong></li><li><strong>do...while循环语句</strong></li><li><strong>for循环语句</strong></li></ul><h4 id="跳转语句">跳转语句</h4><ul><li><strong>break语句</strong></li><li><strong>continue语句</strong></li><li><strong>goto语句</strong>(无条件跳转到标记位置)</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"></span><br><span class="line">cout << <span class="string">"1"</span> << endl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">goto</span> FLAG;</span><br><span class="line"></span><br><span class="line">cout << <span class="string">"2"</span> << endl;</span><br><span class="line">cout << <span class="string">"3"</span> << endl;</span><br><span class="line">cout << <span class="string">"4"</span> << endl;</span><br><span class="line"></span><br><span class="line">FLAG:</span><br><span class="line"></span><br><span class="line">cout << <span class="string">"5"</span> << endl;</span><br><span class="line"></span><br><span class="line"><span class="built_in">system</span>(<span class="string">"pause"</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3id="数组集合内元素同类型连续存放">数组(集合内元素同类型,连续存放)</h3><h4 id="一维数组">一维数组</h4><ul><li><strong>定义方法</strong></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//数据类型 数组名[ 数组长度 ];</span></span><br><span class="line"><span class="comment">//数据类型 数组名[ 数组长度 ] = { 值1,值2 ...};</span></span><br><span class="line"><span class="comment">//数据类型 数组名[ ] = { 值1,值2 ...};</span></span><br></pre></td></tr></table></figure><ul><li><strong>数组的地址</strong></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//数组名用途</span></span><br><span class="line"><span class="comment">//1、可以获取整个数组占用内存空间大小</span></span><br><span class="line"><span class="type">int</span> arr[<span class="number">10</span>] = { <span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">9</span>,<span class="number">10</span> };</span><br><span class="line"></span><br><span class="line">cout << <span class="string">"整个数组所占内存空间为: "</span> << <span class="built_in">sizeof</span>(arr) << endl;</span><br><span class="line">cout << <span class="string">"每个元素所占内存空间为: "</span> << <span class="built_in">sizeof</span>(arr[<span class="number">0</span>]) << endl;</span><br><span class="line">cout << <span class="string">"数组的元素个数为: "</span> << <span class="built_in">sizeof</span>(arr) / <span class="built_in">sizeof</span>(arr[<span class="number">0</span>]) << endl;</span><br><span class="line"></span><br><span class="line"><span class="comment">//2、可以通过数组名获取到数组首地址</span></span><br><span class="line">cout << <span class="string">"数组首地址为: "</span> << (<span class="type">int</span>)(<span class="type">size_t</span>)arr << endl;</span><br><span class="line">cout << <span class="string">"数组中第一个元素地址为: "</span> << (<span class="type">int</span>)(<span class="type">size_t</span>)&arr[<span class="number">0</span>] << endl;</span><br><span class="line">cout << <span class="string">"数组中第二个元素地址为: "</span> << (<span class="type">int</span>)(<span class="type">size_t</span>)&arr[<span class="number">1</span>] << endl;</span><br></pre></td></tr></table></figure><ul><li><strong>数组的排序(冒泡排序)</strong></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//示例:将数组进行升序排序</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="type">int</span> temp;</span><br><span class="line"> <span class="type">int</span> arr[<span class="number">9</span>] = { <span class="number">4</span>,<span class="number">2</span>,<span class="number">8</span>,<span class="number">0</span>,<span class="number">5</span>,<span class="number">7</span>,<span class="number">1</span>,<span class="number">3</span>,<span class="number">9</span> };</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">0</span>;i<<span class="number">9</span>;i++){</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> j=<span class="number">0</span>;j<<span class="number">9</span>-i<span class="number">-1</span>;j++){</span><br><span class="line"> <span class="keyword">if</span>(arr[j]>arr[j+<span class="number">1</span>]){</span><br><span class="line"> temp = arr[j+<span class="number">1</span>];</span><br><span class="line"> arr[j+<span class="number">1</span>] = arr[j];</span><br><span class="line"> arr[j] = temp;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">0</span>;i<<span class="number">9</span>;i++){</span><br><span class="line"> cout << arr[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="二维数组">二维数组</h4><ul><li><strong>定义</strong></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//数据类型 数组名[ 行数 ][ 列数 ];</span></span><br><span class="line"><span class="comment">//数据类型 数组名[ 行数 ][ 列数 ] = { {数据1,数据2 } ,{数据3,数据4 } };</span></span><br><span class="line"><span class="comment">//数据类型 数组名[ 行数 ][ 列数 ] = { 数据1,数据2,数据3,数据4};</span></span><br><span class="line"><span class="comment">//数据类型 数组名[ ][ 列数 ] = { 数据1,数据2,数据3,数据4};</span></span><br></pre></td></tr></table></figure><p>注意:后两种可以一下赋所有元素,然后计算机根据行列数进行判断</p><ul><li><strong>地址</strong></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">cout << <span class="string">"二维数组大小: "</span> << <span class="built_in">sizeof</span>(arr) << endl;</span><br><span class="line">cout << <span class="string">"二维数组一行大小: "</span> << <span class="built_in">sizeof</span>(arr[<span class="number">0</span>]) << endl;</span><br><span class="line">cout << <span class="string">"二维数组元素大小: "</span> << <span class="built_in">sizeof</span>(arr[<span class="number">0</span>][<span class="number">0</span>]) << endl;</span><br><span class="line"></span><br><span class="line">cout << <span class="string">"二维数组行数: "</span> << <span class="built_in">sizeof</span>(arr) / <span class="built_in">sizeof</span>(arr[<span class="number">0</span>]) << endl;</span><br><span class="line">cout << <span class="string">"二维数组列数: "</span> << <span class="built_in">sizeof</span>(arr[<span class="number">0</span>]) / <span class="built_in">sizeof</span>(arr[<span class="number">0</span>][<span class="number">0</span>]) << endl;</span><br><span class="line"></span><br><span class="line"><span class="comment">//地址</span></span><br><span class="line">cout << <span class="string">"二维数组首地址:"</span> << arr << endl;</span><br><span class="line">cout << <span class="string">"二维数组第一行地址:"</span> << arr[<span class="number">0</span>] << endl;</span><br><span class="line">cout << <span class="string">"二维数组第二行地址:"</span> << arr[<span class="number">1</span>] << endl;</span><br><span class="line"></span><br><span class="line">cout << <span class="string">"二维数组第一个元素地址:"</span> << &arr[<span class="number">0</span>][<span class="number">0</span>] << endl;</span><br><span class="line">cout << <span class="string">"二维数组第二个元素地址:"</span> << &arr[<span class="number">0</span>][<span class="number">1</span>] << endl;</span><br></pre></td></tr></table></figure><h3 id="函数">函数</h3>]]></content>
<categories>
<category> 编程 </category>
<category> c++ </category>
</categories>
<tags>
<tag> 编程 </tag>
<tag> c++入门 </tag>
</tags>
</entry>
<entry>
<title>Approximation Algorithms Week 3--Bin Packing,Linear Programming and Rounding</title>
<link href="/post/b4667801.html"/>
<url>/post/b4667801.html</url>
<content type="html"><![CDATA[<p>课程来自<ahref="https://www.coursera.org/learn/approximation-algorithms-part-1/home/week/1">Coursera</a></p><h1 id="bin-packing-problem">Bin packing problem</h1><ul><li><strong>定义</strong>:<spanclass="math inline">\(𝑁\)</span>件物品,每件物品有体积<spanclass="math inline">\({𝑠_𝑖}\)</span>, 不失一般性地,可以约定<spanclass="math inline">\({s_i}\leq1\)</span>, 有容量为<spanclass="math inline">\(1\)</span>箱子,要用尽可能少的箱子容纳所有的物品。</li><li><span class="math inline">\(NP-hard\)</span>问题</li></ul><h2 id="the-next-fit-algorithm">The Next Fit algorithm</h2><ul><li><strong>思想</strong>:依次考虑每个物品, 如果这个物品能放入当前箱子,就放入, 否则关闭当前箱子, 打开一个新的箱子放入这个物品。</li><li><strong>近似比</strong>:<ul><li><span class="math inline">\(proof\)</span>:把编号相邻的箱子配对,考虑箱子<span class="math inline">\(2i−1\)</span>和箱子<spanclass="math inline">\(2i\)</span>。我们打开了箱子<spanclass="math inline">\(2i\)</span>, 说明箱子<spanclass="math inline">\(2i−1\)</span>里面的物品体积之和加上箱子<spanclass="math inline">\(2i\)</span>里面的第一个物品的体积, 必然是大于<spanclass="math inline">\(1\)</span>的,否则按照算法流程会把那个物品放入箱子<spanclass="math inline">\(2i−1\)</span>.</li><li>设按照Next Fit算法用了<spanclass="math inline">\(k\)</span>个箱子,其中最后一个箱子的编号为<spanclass="math inline">\(L\)</span></li><li>有<span class="math inline">\(O P T \geq\left\lceil\sum_{i=1}^Ns_i\right\rceil \geq\left\lceil\sum_{i=1}^{L-1}s_i\right\rceil\)</span></li><li>因为<span class="math inline">\(\sum_{i=1}^{L-1}s_i>\left\lfloor\frac{K}{2}\right\rfloor\)</span>,<spanclass="math inline">\(\left\lfloor\frac{K}{2}\right\rfloor\)</span>是整数,所以<spanclass="math inline">\(\left\lfloor\frac{K}{2}\right\rfloor\leq\left\lceil\sum_{i=1}^{L-1} s_i\right\rceil-1\)</span></li><li>于是有<span class="math inline">\(\frac{K-1}{2}\leq\left\lfloor\frac{K}{2}\right\rfloor \leq O P T-1\)</span></li><li>即<span class="math inline">\(K \leq 2 O P T-1\)</span></li></ul></li><li><strong>算法的紧性:</strong><ul><li>(<span class="math inline">\(2𝑂𝑃𝑇−2\)</span>的例子)有<spanclass="math inline">\(4n\)</span>个物品,满足<spanclass="math inline">\(S_{2 i-1}=\frac{1}{2}, S_{2 i}=\frac{1}{2n}\)</span>,显然<span class="math inline">\(OPT=n+1\)</span>,此时<spanclass="math inline">\(NF\)</span>给出的结果为<spanclass="math inline">\(2n\)</span>.</li></ul></li></ul><h2 id="a-linear-program-for-bin-packingfailed">A Linear program forbin-packing(failed)</h2><ul><li><strong>整数规划模型:</strong><ul><li><strong>变量:</strong><spanclass="math inline">\(\mathrm{x}_{\mathrm{ij}} \in\{\mathbf{0},\mathbf{1}\}\)</span>,当物品<spanclass="math inline">\(i\)</span>放在箱子<spanclass="math inline">\(j\)</span>中时,<spanclass="math inline">\(x_{ij}=1\)</span>.</li><li><strong>约束:</strong><ul><li>约束1:因为每件物品只能放到一个箱子中,对于物品<spanclass="math inline">\(b\)</span>,<spanclass="math inline">\(\mathrm{x}_{\mathrm{b} 1}+\mathrm{x}_{\mathrm{b}2}+\mathrm{x}_{\mathrm{b} 3}+\mathrm{x}_{\mathrm{b} 4}=1\)</span></li><li>约束2:每个箱子内物体的体积和需小于1,<spanclass="math inline">\(\mathbf{x}_{\mathrm{aj}}\mathbf{s}_{\mathbf{a}}+\mathbf{x}_{\mathrm{bj}}\mathrm{s}_{\mathrm{b}}+\cdots+\mathrm{x}_{\mathrm{fj}}\mathrm{s}_{\mathbf{f}} \leq \mathbf{1}\)</span></li></ul></li></ul></li><li><strong>线性规划模型:</strong></li><li><span class="math inline">\(n\)</span> items, <spanclass="math inline">\(K\)</span> bins <spanclass="math inline">\(\forall i: \quad \sum_j x_{i j}=1\)</span> <spanclass="math inline">\(\forall j: \quad \sum_i x_{i j} s_i \leq1\)</span> <span class="math inline">\(\forall i, j: 0 \leq x_{i j} \leq1\)</span></li></ul><p><imgsrc="../images/Approximation-Algorithms-Week-3-Bin-Packing-Linear-Programming-and-Rounding/image-20230125085343476.png" /></p><h2 id="a-special-case1small-things">a special case1:small things</h2><ul><li>例子:当所有物品的<spanclass="math inline">\(s_i<1/3\)</span>,当关闭一个箱子的时候(除了最后一个箱子),这个箱子里面物品体积之和必然<spanclass="math inline">\(\geq2/3\)</span>, 否则还可以接着装物品。假设用了<span class="math inline">\(𝐾\)</span>个箱子, 第一个装入第<spanclass="math inline">\(K\)</span>个箱子的物品编号是<spanclass="math inline">\(𝐿\)</span>, 那么有 <span class="math display">\[\boldsymbol{O P T}>\sum_{i=1}^N s_i>\sum_{i=1}^{L-1} s_i \geq\frac{2}{3}(K-1)\]</span></li></ul><p> 因此<span class="math inline">\(K \leq \frac{3}{2} O PT+1\)</span></p><ul><li>相应地,可以推导所有物品的<spanclass="math inline">\(s_𝑖<\epsilon\)</span>的时候, 有<spanclass="math inline">\(K \leq \frac{1}{1-\epsilon} O P T+1\)</span></li></ul><h2 id="a-special-case2large-itemsfew-sizes">a special case2:largeitems,few sizes</h2><ul><li><p><strong>符号及定义:</strong></p><ul><li><p><strong>Configuration:</strong>指将若干物品装入一个箱子的某种方法。比如往一个箱子中装入2个size为0.2的物品和1个size为0.6的物品。因为物品较大,所以configuration较少。</p><p><imgsrc="../images/Approximation-Algorithms-Week-3-Bin-Packing-Linear-Programming-and-Rounding/image-20230125141910958.png" /></p></li><li><p><span class="math inline">\(A_{c,s}\)</span>:对于configuration<span class="math inline">\(𝑐\)</span>,一个箱子中有<spanclass="math inline">\(A_{C,S}\)</span>个size为<spanclass="math inline">\(s\)</span>的物品。</p></li></ul></li><li><p><strong>近似算法:</strong></p><ul><li><p><strong>Linear Programming:</strong></p><ul><li><p><strong>Input:</strong><spanclass="math inline">\(S={size}\)</span>,对于每种size<spanclass="math inline">\(s\)</span>,有<spanclass="math inline">\(n_s\)</span>个物品.</p></li><li><p><strong>Output:</strong><spanclass="math inline">\(C=\{configurations\}\)</span>,对于configuration<spanclass="math inline">\(c\)</span>所需的箱子数<spanclass="math inline">\(x_c\)</span>。</p></li><li><p>目标函数:<span class="math inline">\(\sum_{\mathbf{c}}\mathbf{x}_{\mathbf{c}}\)</span></p></li><li><p>约束:<span class="math inline">\(\sum_{\mathbf{c}}\mathbf{a}_{\mathbf{s}, \mathbf{c}} \mathbf{x}_{\mathbf{c}} \geq\mathbf{n}_{\mathbf{s}}\)</span></p></li></ul></li><li><p><strong>Rounding:</strong>求出实数线性规划的解向上取整。</p></li></ul></li><li><p><strong>lemma:</strong>假设物体都满足size<spanclass="math inline">\(s\geq\epsilon\)</span>,一共有<spanclass="math inline">\(k\)</span>种不同的size,那么不同configuration的数量<spanclass="math inline">\(\leq K^{\frac{1}{\epsilon}}\)</span></p><ul><li>因为<spanclass="math inline">\(s\geq\epsilon\)</span>,所以对于某个size<spanclass="math inline">\(s\)</span>的configuration数量<spanclass="math inline">\(\leq\frac{1}{\epsilon}\)</span>,因此对于不同的size不同configuration的数量<spanclass="math inline">\(\leq K^{\frac{1}{\epsilon}}\)</span>。</li></ul></li><li><p><strong>算法分析:</strong></p><ul><li>正确性:由线性规划的约束可知此算法是正确的</li><li>近似比:<span class="math inline">\(O P T \geq \sum_c x_c \geq\sum_c\left(\left\lceilx_c\right\rceil-1\right)\)</span>,configuration数量<spanclass="math inline">\(\leqK^{\frac{1}{\epsilon}}\)</span>,因此近似解<spanclass="math inline">\(\leq O P T+K^{\frac{1}{D}}\)</span>。</li></ul></li></ul><h2 id="a-special-case3large-items-many-distinct-sizesless-special">aspecial case3:large items, many distinct sizes(less special)</h2>]]></content>
<categories>
<category> coursera </category>
<category> Approximation Algorithms Part I </category>
</categories>
<tags>
<tag> 近似算法 </tag>
<tag> Bin-Packing </tag>
</tags>
</entry>
<entry>
<title>Approximation Algorithms Week 2--Knapsack and Rounding</title>
<link href="/post/4b0b12b.html"/>
<url>/post/4b0b12b.html</url>
<content type="html"><![CDATA[<p>课程来自<ahref="https://www.coursera.org/learn/approximation-algorithms-part-1/home/week/1">Coursera</a></p><h1 id="the-knapsack-problem">The Knapsack Problem</h1><h2 id="problem-dedinition">Problem Dedinition</h2><ul><li><spanclass="math inline">\(𝑁\)</span>件物品,每件物品有一个体积<spanclass="math inline">\({𝑠_𝑖}\)</span>和价值<spanclass="math inline">\({v_i}\)</span>, 现在有一个容量是<spanclass="math inline">\(𝐵\)</span>的背包,要选一些物品装进背包,使得价值之和最大。约定不会有体积超过背包容积的物体。</li><li>背包问题是<span class="math inline">\(NP-Hard\)</span>问题</li></ul><h2 id="naive-greedy-algorithmm">Naive greedy algorithmm</h2><ul><li><strong>思想</strong>:由于希望总体积更小,总价值更大。计算每件物品的<spanclass="math inline">\(\frac{\mathbf{s}_{\mathbf{i}}}{\mathbf{v}_{\mathbf{i}}}\)</span>,从小到大排列依次放入背包。</li><li><strong>评价</strong>:<imgsrc="../images/Approximation-Algorithms-Week-2-Knapsack-and-Rounding/image-20230108172826038.png"alt="image-20230108172826038" /></li></ul><h2 id="special-case-1物品体积与价值相等">special case1:物品体积与价值相等</h2><ul><li><strong>a greedy algorithm</strong><ul><li><strong>思想</strong>:将物品按价值降序排列,依次放入背包。</li><li><strong>近似比证明</strong>:该算法的近似比为2<ul><li><em><spanclass="math inline">\(proof\)</span></em>:已知任意物品的体积都小于背包,则最终背包中至少包含一件物品。令最终放入背包的物品总体积为<spanclass="math inline">\(v\)</span>,第一件放不进背包的物品体积为<spanclass="math inline">\(v_i\)</span>,显然<span class="math inline">\(v +v_i \geq B\)</span>。又因为该算法事先将物品按体积降序排列,则<spanclass="math inline">\(v \geq v_i\)</span>,因此<spanclass="math inline">\(v \geqB/2\)</span>,有物品装不进的时候背包至少是半满的,即该算法的近似比为2。</li></ul></li></ul></li></ul><h2id="special-case-2在case1的基础上物品与背包体积较小且为整数因此此问题的动态规划算法是多项式时间的">specialcase2:在case1的基础上,物品与背包体积较小且为整数(因此此问题的动态规划算法是多项式时间的)</h2><ul><li><strong>Special dynamicprogram</strong>:由于物品价值都比较小,考虑动态规划。<spanclass="math inline">\(A[i,v]\)</span>表示<spanclass="math inline">\(i\)</span>项物品的子集的体积和是否可以达到<spanclass="math inline">\(v\)</span>。<ul><li><imgsrc="../images/Approximation-Algorithms-Week-2-Knapsack-and-Rounding/image-20230117055558615.png" /></li><li><strong>analysis:</strong><ul><li>此问题的目标是使装入背包的物品的体积和<spanclass="math inline">\(v\)</span>最大,此时存在<spanclass="math inline">\(n\)</span>个物品的子集使得它们的体积和刚好达到<spanclass="math inline">\(v\)</span>,即<spanclass="math inline">\(A[n,v]\)</span>为<spanclass="math inline">\(true\)</span>。</li><li><span class="math inline">\(v_1,v_2,...,v_n\)</span>分别为物品<spanclass="math inline">\(1,2,...,n\)</span>的体积,因为单个物品的体积总小于<spanclass="math inline">\(B\)</span>,所以<spanclass="math inline">\(A[1,v_1]\gets true\)</span>。</li><li>当考虑是否将第<spanclass="math inline">\(i\)</span>件物品放入背包时,<spanclass="math inline">\(A[i,v](v<v_i)=A[i-1,v]\)</span>,当<spanclass="math inline">\(v\geq v_i\)</span>时有两种情况:<ul><li>(1)第<spanclass="math inline">\(i\)</span>件物品暂时不装入背包,<spanclass="math inline">\(A[i,v]=A[i-1,v]\)</span></li><li>(2)第<spanclass="math inline">\(i\)</span>件物品暂时装入背包,<spanclass="math inline">\(A[i,v]=A[i-1,v-v_i]\)</span></li></ul></li><li>经过上步得到的<span class="math inline">\(\max\{v:A[i,v] \; is \;true \}\)</span>为从<spanclass="math inline">\(i\)</span>件物品中挑选物品放入背包时得到的最大体积和。因此当从<spanclass="math inline">\(n\)</span>件物品中挑选时,问题的解为<spanclass="math inline">\(\max\{v:A[n,v] \; is \; true \}\)</span>。</li></ul></li></ul></li></ul><h2id="special-case-3背包体积与物品的价值体积较小且为整数物品的价值vleq-n体积与价值不相等一个略普遍的例子">specialcase 3:背包体积与物品的价值体积较小且为整数,物品的价值<spanclass="math inline">\(v\leqN\)</span>,体积与价值不相等(一个略普遍的例子)</h2><ul><li><strong>dynamic program:</strong><spanclass="math inline">\(A[i,v]\)</span>表示<spanclass="math inline">\(i\)</span>项物品子集的价值和达到<spanclass="math inline">\(v\)</span>时的最小体积和。<ul><li><imgsrc="../images/Approximation-Algorithms-Week-2-Knapsack-and-Rounding/image-20230117073321175.png" /></li><li><strong>算法复杂度:</strong><spanclass="math inline">\(O(n^{2}N)\)</span></li></ul></li></ul><h2 id="approximation-algorithm-for-general-case大非整">ApproximationAlgorithm for general case(大,非整)</h2><ul><li><p><strong>general case:</strong>物品个数<spanclass="math inline">\(n\)</span>,背包的体积<spanclass="math inline">\(B\)</span></p></li><li><p><strong>思想:</strong>scale(使每个物品<spanclass="math inline">\(i\)</span>的价值<spanclass="math inline">\(0<v_i\leq N\)</span>) andround(使每个物品的体积为整数)</p><p><imgsrc="../images/Approximation-Algorithms-Week-2-Knapsack-and-Rounding/image-20230117225927429.png" /></p></li><li><p><strong>算法:</strong></p><ul><li><strong>step1:</strong>丢弃体积大于<spanclass="math inline">\(B\)</span>的物品。</li><li><strong>step2:</strong>令<spanclass="math inline">\(N=100n\)</span></li><li><strong>step3:</strong>对每个物品的体积进行scaling和rounding,<spanclass="math inline">\(\mathbf{v}_{\mathbf{i}}^{\prime}\leftarrow\left\lfloor\mathbf{v}_{\mathbf{i}} \times\frac{\mathbf{N}}{\max _{\mathbf{j}}\mathbf{v}_{\mathbf{j}}}\right\rfloor\)</span></li><li><strong>step4:</strong>对参数为<spanclass="math inline">\(B\)</span>,<spanclass="math inline">\((s_i,v_i')_i\)</span>的背包问题进行动态规划,得到的原问题的解</li></ul></li><li><p><strong>算法复杂度:</strong><spanclass="math inline">\(100*n^3\)</span></p></li><li><p><strong>算法分析:</strong></p><ul><li><p><strong>notation:</strong></p><ul><li><span class="math inline">\(S\)</span> outputitems(scaled、rounded)</li><li><span class="math inline">\(S^*\)</span> outputitems(scaled、unrounded)</li><li><span class="math inline">\(\alpha=M/\max v_i\)</span> 放缩系数</li></ul></li><li><p><strong>定理:</strong>该算法得到的<spanclass="math inline">\(value\geq 0.99 OPT\)</span>,时间复杂度为<spanclass="math inline">\(O(poly(n))\)</span></p><ul><li><p><span class="math inline">\(proof\)</span>:</p><ul><li><p>由于<span class="math inline">\(S\)</span>相比<spanclass="math inline">\(S^*\)</span>经过了放缩(乘系数<spanclass="math inline">\(\alpha\)</span>并向下取整),<spanclass="math inline">\(S^*\)</span>是最优解,所以有<spanclass="math inline">\(\sum_{\mathbf{S}} \mathbf{v}_{\mathbf{i}}^{\prime}\geq \sum_{\mathbf{S}^*}\mathbf{v}_{\mathbf{i}}^{\prime}\)</span></p></li><li><p>由放缩公式<spanclass="math inline">\(\mathbf{v}_{\mathbf{i}}^{\prime}\leftarrow\left\lfloor\mathbf{v}_{\mathbf{i}} \times\alpha\right\rfloor\)</span>知<spanclass="math inline">\(\mathbf{v}_{\mathbf{i}}^{\prime}>\alpha\mathbf{v}_{\mathbf{i}}-\mathbf{1}\)</span>,因此<spanclass="math inline">\(\sum_{\mathbf{S}^*}\mathbf{v}_{\mathbf{i}}^{\prime}>\alpha \sum_{\mathbf{S}^*}\mathbf{V}_{\mathbf{i}}-\mathbf{n}\)</span></p></li><li><p>综上,</p></li><li><p><span class="math display">\[\begin{aligned}\operatorname{Value}(\mathbf{S}) & =\sum_{\mathbf{S}}\mathbf{v}_{\mathbf{i}} \\& =\frac{1}{\alpha}\sum_{\mathbf{S}}\left(\alpha \mathbf{v}_{\mathbf{i}}\right) \\&\geq \frac{1}{\alpha} \sum_{\mathbf{S}}\mathbf{v}_{\mathbf{i}}^{\prime}\\& \geq \frac{\mathbf{1}}{\alpha}\sum_{\mathbf{S}^*} \mathbf{v}_{\mathbf{i}}^{\prime} \\& \geq\frac{\mathbf{1}}{\alpha}\left[\alpha \sum_{\mathbf{S}^*}\mathbf{v}_{\mathbf{i}}-\mathbf{n}\right] \\& =\mathbf{O P}\mathbf{T}-\frac{\mathbf{n}}{\alpha} \\& =\mathbf{O P}\mathbf{T}-\frac{\mathbf{n} \times \max\mathbf{v}_{\mathbf{i}}}{\mathbf{N}}\end{aligned}\]</span></p></li><li><p>又因为<span class="math inline">\(OPT\geq \maxv_i\)</span></p></li><li><p>代入得到 <span class="math inline">\(Value(\mathbf{S}) \geq\mathbf{O P} \mathbf{T}-\frac{\mathbf{n}}{\mathbf{N}} \mathbf{O PT}\)</span></p></li><li><p>当<span class="math inline">\(\mathbf{N}=\mathbf{1 0 0} \times\mathbf{n}\)</span>时, <span class="math inline">\(Value(S) \geq .99\times\)</span> OPT</p></li></ul></li></ul></li></ul></li></ul><h2 id="knapsack问题的近似算法系统">knapsack问题的近似算法系统</h2><ul><li><strong>定理:</strong>在上述算法中令<spanclass="math inline">\(N=1000n\)</span>,得到的<spanclass="math inline">\(value\geq0.999OPT\)</span>,时间复杂度是多项式时间的。</li><li><strong>knapsack的近似算法系统:</strong>对于任意<spanclass="math inline">\(\epsilon>0\)</span>,可以利用近似算法得到满足<spanclass="math inline">\(\mid Value(Output)-OPT \mid \leq \epsilon \times\mathrm{OPT}\)</span>的解,<spanclass="math inline">\(\epsilon\)</span>越小,解越接近<spanclass="math inline">\(OPT\)</span>,运算时间变大.</li></ul>]]></content>
<categories>
<category> coursera </category>
<category> Approximation Algorithms Part I </category>
</categories>
<tags>
<tag> 近似算法 </tag>
<tag> Knapsack </tag>
</tags>
</entry>
<entry>
<title>Approximation Algorithms Week 1--Vertex cover and Linear Programmng</title>
<link href="/post/d8762d8c.html"/>
<url>/post/d8762d8c.html</url>
<content type="html"><![CDATA[<p>课程来自<ahref="https://www.coursera.org/learn/approximation-algorithms-part-1/home/week/1">Coursera</a></p><h1 id="前置知识">前置知识</h1><h2 id="关于组合优化问题">关于组合优化问题</h2><ul><li><p>应用于安排课程、计划运输路线等一系列<spanclass="math inline">\(NP-hard\)</span>问题(没有多项式时间的解)</p></li><li><p>解决<span class="math inline">\(NP-hard\)</span>问题的方法:</p><ol type="1"><li>限制算法是多项式时间的</li><li>放弃寻找最优解,而是去寻找足够好的解。</li><li>对于现实中复杂的问题,研究其理想化的版本。</li></ol></li></ul><h2 id="p问题np问题npc问题">P问题、NP问题、NPC问题</h2><ul><li><p><strong>多项式时间</strong>(polynomialtime):可用多项式表示的时间复杂度,如<spanclass="math inline">\(O(1)\)</span>、<span class="math inline">\(O(\logN)\)</span>、<span class="math inline">\(O(N^2)\)</span></p></li><li><p><strong>约化</strong>(Reducibility):问题<spanclass="math inline">\(A\)</span>可以约化为问题<spanclass="math inline">\(B\)</span>,即用问题<spanclass="math inline">\(B\)</span>的方法解决问题<spanclass="math inline">\(A\)</span>,此约化是多项式的。例:用求解一元一次方程的方法约化为求解一元二次方程的方法。</p></li><li><p><strong><spanclass="math inline">\(P\)</span>问题</strong>:一类可在多项式时间内解决的问题的集合。</p></li><li><p><strong><spanclass="math inline">\(NP\)</span>问题</strong>:一类问题,此类问题可在多项式时间内验证。</p></li><li><p><strong><spanclass="math inline">\(NP-Complete\)</span>问题</strong>:一类问题<spanclass="math inline">\(X\)</span>,任意<spanclass="math inline">\(NP\)</span>问题<spanclass="math inline">\(Y\)</span>都可以在多项式式时间内约化为问题<spanclass="math inline">\(X\)</span>。</p><ul><li><p><strong>证明一个问题是<spanclass="math inline">\(NPC\)</span>问题:</strong></p><ol type="1"><li>此问题为<span class="math inline">\(NP\)</span>问题</li><li>一个已知的<spanclass="math inline">\(NPC\)</span>问题可以约化为此问题</li></ol></li><li><p><strong>Pick all the correct statements.If a problem <spanclass="math inline">\(H\)</span> is <spanclass="math inline">\(NP-Complete\)</span>, then...</strong></p><p>☑For any problem <span class="math inline">\(L\)</span> in <spanclass="math inline">\(NP\)</span>, there is a polynomial-time reductionfrom <span class="math inline">\(L\)</span> to <spanclass="math inline">\(H\)</span>.</p><p>☑For any problem <span class="math inline">\(L\)</span> in <spanclass="math inline">\(P\)</span>, there is a polynomial-time reductionfrom <span class="math inline">\(L\)</span> to <spanclass="math inline">\(H\)</span>.</p><p>☐<span class="math inline">\(H\)</span> belongs to the class <spanclass="math inline">\(P\)</span>.</p><p>☑<span class="math inline">\(H\)</span> belongs to the class <spanclass="math inline">\(NP\)</span>.</p><p>☑If there exists a polynomial-time algorithm for the Hamiltonian pathproblem then there exists a polynomial-time algorithm for <spanclass="math inline">\(H\)</span>.</p><p>☑An output to problem H is either "yes" or "no".</p><p>☑If there exists a polynomial-time algorithm for H then there existsa polynomial-time algorithm for the Hamiltonian path problem.</p></li></ul></li><li><p><strong><spanclass="math inline">\(NP-Hard\)</span>问题</strong>:一类问题所组成的集合,此类问题的范围比<spanclass="math inline">\(NPC\)</span>问题广,不一定为决策问题,不包含于<spanclass="math inline">\(NP\)</span>问题。任何<spanclass="math inline">\(NPC\)</span>问题可在多项式时间内约化为<spanclass="math inline">\(NP-Hard\)</span>问题。</p><ul><li><p><strong>Pick all the correct statements.If a problem <spanclass="math inline">\(H\)</span> is <spanclass="math inline">\(NP-Hard\)</span>, then...</strong></p><p>☑For any problem <span class="math inline">\(L\)</span> in <spanclass="math inline">\(P\)</span>, there is a polynomial-time reductionfrom <span class="math inline">\(L\)</span> to <spanclass="math inline">\(H\)</span>.</p><p>☐<span class="math inline">\(H\)</span> belongs to the class <spanclass="math inline">\(P\)</span>.</p><p>☐<span class="math inline">\(H\)</span> belongs to the class <spanclass="math inline">\(NP\)</span>.</p><p>☑If there exists a polynomial-time algorithm for <spanclass="math inline">\(H\)</span> then there exists a polynomial-timealgorithm for the Hamiltonian path problem.</p><p>☐If there exists a polynomial-time algorithm for the Hamiltonian pathproblem then there exists a polynomial-time algorithm for <spanclass="math inline">\(H\)</span>.</p><p>☐An output to problem <span class="math inline">\(H\)</span> is "yes"or "no".</p><p>☑For any problem <span class="math inline">\(L\)</span> in <spanclass="math inline">\(NP\)</span>, there is a polynomial-time reductionfrom <span class="math inline">\(L\)</span> to <spanclass="math inline">\(H\)</span>.</p></li></ul></li></ul><p><imgsrc="../images/Approximation-Algorithms-Week-1-Vertex-cover-and-Linear-Programmng/image-20230107212557061.png" /></p><p><ahref="https://image.baidu.com/search/detail?ct=503316480&z=undefined&tn=baiduimagedetail&ipn=d&word=NP问题&step_word=&ie=utf-8&in=&cl=2&lm=-1&st=undefined&hd=undefined&latest=undefined&copyright=undefined&cs=1862044270,1140788464&os=2330962426,1604755770&simid=1862044270,1140788464&pn=10&rn=1&di=7169026086108397569&ln=1277&fr=&fmq=1673097846472_R&fm=&ic=undefined&s=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&is=0,0&istype=0&ist=&jit=&bdtype=0&spn=0&pi=0&gsm=1e&objurl=https%3A%2F%2Fi.stack.imgur.com%2FcSe62.png&rpstart=0&rpnum=0&adpicid=0&nojc=undefined&dyTabStr=MCwxLDMsMiw0LDUsNyw4LDYsOQ%3D%3D"><imgsrc="../images/Approximation-Algorithms-Week-1-Vertex-cover-and-Linear-Programmng/u=2541031885,1494691757&fm=253&fmt=auto&app=138&f=JPG.jpeg"alt="img" /></a></p><h1 id="the-vertex-cover-problem">The Vertex cover problem</h1><h2 id="problem-dedinition">Problem Dedinition</h2><ul><li>最小点覆盖,即给出一个无向图,求一个最小的点集<spanclass="math inline">\(S\)</span>,使得每条边都至少有一个顶点在这个点集里。</li><li><strong>Example</strong>:</li></ul><p><imgsrc="../images/Approximation-Algorithms-Week-1-Vertex-cover-and-Linear-Programmng/image-20230107221118517.png" /></p><ul><li><spanclass="math inline">\(proof\)</span>:此图不可被五个点的集合覆盖<ul><li>此图的外部由一个五边形构成,一个五边形的覆盖集至少含有三个点;此图的内部由一个五角星构成,五角星是另一种形式的五边形,它的覆盖集也至少包含三个点。因此这个图的覆盖集至少包含六个顶点。</li></ul></li></ul><h2 id="an-integer-program-for-vertex-cover">An Integer program forvertex cover</h2><ul><li><p>三部分:变量、约束、目标</p><ul><li><p>变量: <span class="math display">\[ \left\{x_u \mid u \in V\right\} \]</span></p></li><li><p>约束: <span class="math display">\[ \begin{gathered} \forall u \in V: x_u=0 o r 1 \\ \forall\{u, v\} \in E: x_u+x_v \geq 1 \end{gathered} \]</span></p></li><li><p>目标:<span class="math inline">\(min \sum_u w_ux_u\)</span></p></li><li><p>例:</p></li></ul></li></ul><p><imgsrc="../images/Approximation-Algorithms-Week-1-Vertex-cover-and-Linear-Programmng/image-20230108003338843.png" /></p><h2 id="a-linear-programming-relaxation">A linear programmingrelaxation</h2><ul><li>Integer program模型</li></ul><p><span class="math display">\[\begin{aligned}& \min c_1 x_1+c_2 x_2+\cdots+c_n x_n \\& \begin{cases}a_{11} x_1+a_{12} x_2+\cdots+a_{1 n} x_n & \geqb_1 \\a_{21} x_1+a_{22} x_2+\cdots+a_{2 n} x_n & \geq b_2 \\\cdots & \\a_{m 1} x_1+a_{m 2} x_2+\cdots+a_{m n} x_n & \geq b_m \\\forall i: \quad 0 \leq x_i \leq 1 & \\\forall i: \quad x_i \text { integer }\end{cases} \\&\end{aligned}\]</span></p><ul><li>Integer program是<spanclass="math inline">\(NP-Hard\)</span>问题</li><li>linear program模型</li></ul>$$<span class="math display">\[\begin{aligned}& \min c_1 x_1+c_2 x_2+\cdots+c_n x_n \\& \begin{cases}a_{11} x_1+a_{12} x_2+\cdots+a_{1 n} x_n & \geqb_1 \\a_{21} x_1+a_{22} x_2+\cdots+a_{2 n} x_n & \geq b_2 \\\cdots & \\a_{m 1} x_1+a_{m 2} x_2+\cdots+a_{m n} x_n & \geq b_m \\\forall i: \quad 0 \leq x_i \leq 1 & \\\forall i: \quad x_i \text { real number }\end{cases} \\&\end{aligned}\]</span><p>$$</p><ul><li><p>linear program是多项式时间可解的问题</p></li><li><p>因为linear program模型的求解速度优于Integerprogram,因此设计出vertex cover问题的linear program</p><ul><li><p>变量: <span class="math display">\[ \left\{x_u \mid u \in V\right\} \]</span></p></li><li><p>约束: <span class="math display">\[ \begin{aligned} & \forall u \in V: 0 \leq x_u \leq 1 \\ & \forall\{u, v\} \in E: x_u+x_v \geq 1 \end{aligned} \]</span></p></li><li><p>目标:<span class="math inline">\(min \sum_u w_ux_u\)</span></p></li></ul></li></ul><h2 id="vertex-cover问题的近似算法1">vertexcover问题的近似算法(1)</h2><ul><li><p><strong>思想</strong>:在此问题的整数规划的基础上允许<spanclass="math inline">\(x_u\)</span>不为整数,但需要满足<spanclass="math inline">\(0 \leq x_u \leq1\)</span>,即首先求得线性规划的解<spanclass="math inline">\(x_u^*\)</span>,再通过某种变换得到整数规划的解<spanclass="math inline">\(z_u\)</span></p></li><li><p><strong>转化</strong>:对<spanclass="math inline">\(x_u^*\)</span>进行四舍五入 <spanclass="math display">\[z_u= \begin{cases}1 & \text { if } x_u^* \geq 0.5 \\ 0 & \text {otherwise }\end{cases}\]</span></p></li><li><p><strong>正确性证明</strong>:由于线性规划得到的解满足<spanclass="math inline">\(x_u^*+x_v^* \geq 1\)</span>,则必有<spanclass="math inline">\(x_u^*\geq 0.5\)</span>或<spanclass="math inline">\(x_v^*\geq 0.5\)</span>,所以<spanclass="math inline">\(x_u\geq 1或x_v\geq 1\)</span>,满足<spanclass="math inline">\(x_u+x_v \geq1\)</span>的条件,因此该算法得到的点集属于点覆盖。</p></li><li><p><strong>近似比证明</strong>:</p><ul><li>首先(1)当<span class="math inline">\(x_u^*\geq1/2\)</span>时,<span class="math inline">\(z_u=1\)</span>(2)<spanclass="math inline">\(x_u^*\leq 1/2\)</span>时,<spanclass="math inline">\(z_u=0\)</span>,可以得到<spanclass="math inline">\(z_u\leq2x_u^*\)</span>。又因为<spanclass="math inline">\(x^*\)</span>是对原整数规划放宽约束所得到的最优解,因此<spanclass="math inline">\(\sum_{\mathbf{u}} \mathbf{w}_{\mathbf{u}}\mathbf{x}_{\mathbf{u}}^* \leq \mathrm{OPT}\)</span>。综上,<spanclass="math inline">\(\sum_{\mathbf{u}} \mathbf{w}_{\mathbf{u}}\mathbf{z}_{\mathbf{u}} \leq 2\sum_{\mathbf{u}} \mathbf{w}_{\mathbf{u}}\mathbf{x}_{\mathbf{u}}^* \leq 2\mathrm{OPT}\)</span>,近似比为2。</li></ul></li><li><p><strong>算法的紧性</strong>:求正八边形的最小覆盖集。</p></li></ul><h2 id="half-integrality定理证明">Half integrality定理证明</h2><ul><li><p><strong>定理</strong>:对于vertexcover问题的线性规划算法,一定存在某个最优解<spanclass="math inline">\(x_i\)</span>,任意<spanclass="math inline">\(x_i\)</span>满足<span class="math inline">\(x_i\in\left\{0, \frac{1}{2}, 1\right\}\)</span>.(Half Integrality)</p><ul><li><p><span class="math inline">\(proof\)</span>:</p><ul><li><p>思想:证明任意最优解可以在多项式时间内调整为上面的形式</p></li><li><p>设vertex cover问题线性规划的最优解为<spanclass="math inline">\(\{x_i\}\)</span>,取足够小的<spanclass="math display">\[\epsilon\]</span>构造新的解<spanclass="math inline">\(\{y_i\}\)</span>和<spanclass="math inline">\(\{z_i\}\)</span>: <span class="math display">\[y_i=\left\{\begin{array}{lr}x_i, & x_i \in\{0,0.5,1\} \\x_i+\epsilon, & 0<x_i<0.5 \\x_i-\epsilon, & 0.5<x_i<1\end{array}\right.\]</span></p><p><span class="math display">\[z_i=\left\{\begin{array}{lr}x_i, & x_i \in\{0,0.5,1\} \\x_i-\epsilon, & 0<x_i<0.5 \\x_i+\epsilon, & 0.5<x_i<1\end{array}\right.\]</span></p><p>回顾LP问题的约束条件: <span class="math display">\[\begin{aligned}& \forall u \in V: 0 \leq x_u \leq 1 \\& \forall\{u, v\} \in E: x_u+x_v \geq 1\end{aligned}\]</span> 观察构造的解,发现<spanclass="math inline">\(\{y_i\}\)</span>和<spanclass="math inline">\(\{z_i\}\)</span>均满足线性规划的约束,属于可行解。</p></li><li><p>由于<spanclass="math inline">\(\{x_i\}\)</span>是最优解,所以有<spanclass="math inline">\(\sum w_i x_i \leq \sum w_i y_i, \sum w_i x_i \leq\sum w_i z_i\)</span></p><p>又有<span class="math inline">\(\sum w_i y_i+\sum w_i z_i=2 \sum w_ix_i\)</span></p><p>因此<span class="math inline">\(\sum w_i x_i=\sum w_i y_i=\sum w_iz_i\)</span>,即<span class="math inline">\(\{y_i\}\)</span>和<spanclass="math inline">\(\{z_i\}\)</span>也是最优解</p></li><li><p>考虑<spanclass="math inline">\(\epsilon>0\)</span>不断增大,直到将不属于<spanclass="math inline">\(\{0, \frac{1}{2},1\}\)</span>的变量变到此区间之间。若变量已经属于区间<spanclass="math inline">\(\left\{0, \frac{1}{2},1\right\}\)</span>,将不会再改变,因此对变量进行的松弛操作是多项式时间的。</p></li></ul></li></ul></li></ul><h2 id="vertex-cover问题的近似算法2">vertexcover问题的近似算法(2)</h2><ul><li><p><strong>考虑一类特殊的图</strong><spanclass="math inline">\(G\)</span>:四染色图,即用4种颜色来对<spanclass="math inline">\(G\)</span>的顶点进行染色,使得构成每一条边<spanclass="math inline">\((u,v)\)</span>的两个顶点颜色不同。</p></li><li><p><strong>对4-染色图的近似算法</strong>:</p><ul><li><strong>step1</strong>:将图<spanclass="math inline">\(G\)</span>进行4-染色</li><li><strong>step2</strong>:对<spanclass="math inline">\(G\)</span>进行线性规划,得到解<spanclass="math inline">\(\{x_i\}\)</span>,对解进行改造使其满足<spanclass="math inline">\(x_i \in\left\{0, \frac{1}{2},1\right\}\)</span>。</li><li><strong>step3</strong>:令<spanclass="math inline">\(S=\emptyset\)</span>,<spanclass="math inline">\(S=S\cup\{v|x_v=1\}\)</span>.</li><li><strong>step4</strong>:将<spanclass="math inline">\(\{v|x_v=1/2\}\)</span>按照颜色进行分类,经过排序,得到<spanclass="math inline">\(V_0^{\frac{1}{2}}, V_1^{\frac{1}{2}},V_2^{\frac{1}{2}}, V_3^{\frac{1}{2}}\)</span>,满足<spanclass="math inline">\(\left|V_0^{1 / 2}\right| \leq\left|V_1^{1 /2}\right| \leq\left|V_2^{1 / 2}\right| \leq\left|V_3^{1 /2}\right|\)</span>。</li><li><strong>step5</strong>:<spanclass="math inline">\(S=S\cup\{V_0^{\frac{1}{2}}\}\cup\{V_1^{\frac{1}{2}}\}\cup\{V_2^{\frac{1}{2}}\}\)</span>,<spanclass="math inline">\(S\)</span>为算法的解。</li></ul></li><li><p><strong>算法近似比证明</strong>:</p><ul><li><p><span class="math inline">\(proof\)</span>:</p><ul><li><p>vertex cover问题线性规划模型的目标值 <spanclass="math display">\[val(X)=\sum_u w_u x_u=\frac{1}{2}\left|V^{\frac{1}{2}}\right|+\left|V^1\right|\]</span></p></li><li><p>由于<span class="math inline">\(\left|V_0^{1 / 2}\right|\leq\left|V_1^{1 / 2}\right| \leq\left|V_2^{1 / 2}\right|\leq\left|V_3^{1 / 2}\right|\)</span>,<spanclass="math inline">\(\left|V_3^{\frac{1}{2}}\right| \geq \frac{1}{4}\left|V^{\frac{1}{2}}\right|\)</span></p></li><li><p>因此<spanclass="math inline">\(\left|V_0^{\frac{1}{2}}\right|+\left|V_1^{\frac{1}{2}}\right|+\left|V_2^{\frac{1}{2}}\right|\leq \frac{3}{4} \left|V^{\frac{1}{2}}\right|\)</span></p></li><li><p>则 <span class="math display">\[\begin{aligned}\left|S\right|&=\left|V^1\right|+\left|V_0^{\frac{1}{2}}\right|+\left|V_1^{\frac{1}{2}}\right|+\left|V_2^{\frac{1}{2}}\right|\\&\leq \frac{3}{4} \left|V^{\frac{1}{2}}\right|+\left|V^1\right| \\&\leq \operatorname{val}(X)+\frac{1}{4}\left|V^{\frac{1}{2}}\right|+\frac{1}{2}\left|V^1\right| \\&= \frac{3}{2} \operatorname{val}(X)\end{aligned}\]</span></p></li><li><p>最终可得 <span class="math display">\[|S| \leq \frac{3}{2} \operatorname{val}(x) \leq \frac{3}{2} O P T\]</span></p></li></ul></li></ul></li><li><p><strong>算法的正确性</strong>:</p><ul><li><span class="math inline">\(proof\)</span>:<ul><li>由于对于任意边<span class="math inline">\(e(u,v)\)</span>,<spanclass="math inline">\(x_u+x_v \geq 1\)</span>,<spanclass="math inline">\(x_i \in\left\{0, \frac{1}{2},1\right\}\)</span>,考虑三种情形:</li><li>(1)若<spanclass="math inline">\(x_u,x_v\)</span>中有一个为1,则该点在<spanclass="math inline">\(S\)</span>中,此边被覆盖;</li><li>(2)若<spanclass="math inline">\(x_u,x_v\)</span>中有一个为0,则令一个为1,此边被覆盖;</li><li>(3)若<spanclass="math inline">\(x_u=x_v=1/2\)</span>,因为两点共同构成一条边,所以颜色不同,不会都在<spanclass="math inline">\(\left|V_3^{1 /2}\right|\)</span>中,因此两点中至少有一个点在<spanclass="math inline">\(S\)</span>中,从而此边被覆盖。</li><li>综上,算法所得到<span class="math inline">\(S\)</span>是图<spanclass="math inline">\(G\)</span>的覆盖集。</li></ul></li></ul></li></ul><h1 id="参考资料">参考资料</h1><ul><li><p><ahref="https://blog.csdn.net/qq_41835091/article/details/118632164">P问题、NP问题、NPC问题</a></p></li><li><p><ahref="https://blog.csdn.net/gorray/article/details/122398901">hexo的数学公式渲染</a></p></li><li><p><ahref="https://zhenweiliu.gitee.io/blog/2019/07/26/Approximation-Algorithm-1-Vertex-Cover/">vertexcover问题及算法</a></p></li></ul>]]></content>
<categories>
<category> coursera </category>
<category> Approximation Algorithms Part I </category>
</categories>
<tags>
<tag> 近似算法 </tag>
<tag> Vertex cover </tag>
<tag> Linear Programmng </tag>
</tags>
</entry>
<entry>
<title>The bin-packing problem</title>
<link href="/post/c75b23f2.html"/>
<url>/post/c75b23f2.html</url>
<content type="html"><![CDATA[<p>本节取自《The Design of Approximation-Algorithms》3.3</p><h1 id="the-bin-packing-problem">The bin-packing problem</h1><h2 id="定义">定义</h2><ul><li><p><span class="math inline">\(n\)</span>件物品,每件物品有体积<spanclass="math inline">\({a_𝑖}\)</span>, ,约定<spanclass="math inline">\(0<{a_1} \leq {a_2}...\leq {a_n}<1\)</span>,有容量为<span class="math inline">\(1\)</span>箱子,要用尽可能少的箱子容纳所有的物品。</p></li><li><p><imgsrc="../images/The-bin-packing-problem/image-20230109034409655.png" /></p><ul><li><p><strong><span class="math inline">\(proof1\)</span>.证明Binpacking问题的Decisionversion是NP-complete。</strong></p><ul><li><p><strong>思想</strong>:将已知是<spanclass="math inline">\(NPC\)</span>问题的PartitionProblem约化到Binpacking问题</p></li><li><p><imgsrc="../images/The-bin-packing-problem/image-20230109034901090.png" /></p></li><li><p>Decision version of Binpacking: 给出<spanclass="math inline">\(K\)</span>个背包, 问能不能装下所有物品。</p></li><li><p><strong>证明</strong>:构造一个Binpacking问题的instance: <spanclass="math display">\[K=2, s_i=\frac{2 a_i}{\sum_{i=1}^n a_i}\]</span> 一个Partition相当于得到将这些物品装入2个箱子的解</p></li></ul></li><li><p><span class="math inline">\(proof2\)</span>.证明Binpacking不存在<spanclass="math inline">\(𝛼−𝑎𝑝𝑝𝑟𝑜𝑥𝑖𝑚𝑎𝑡𝑖𝑜𝑛(𝛼<3/2)\)</span>, 除非<spanclass="math inline">\(P=NP\)</span>.</p><ul><li><strong>思想</strong>:反证法</li><li><strong>证明</strong>:假设存在一个 <spanclass="math inline">\(\left(\frac{3}{2}-\epsilon\right)-\)</span>approximation,任意Partition Problem的instance <spanclass="math inline">\(𝐼_𝑃\)</span>可以用<spanclass="math inline">\(Q_1\)</span>的方法,构造出一个对应的Binpacking的instance<span class="math inline">\(𝐼_𝐵\)</span>, 显然<spanclass="math inline">\(𝑂𝑃𝑇(𝐼_𝐵)\geq2\)</span>. 要回答<spanclass="math inline">\(𝐼_𝑃\)</span>是不是yes, 实际上就是问<spanclass="math inline">\(𝑂𝑃𝑇(𝐼_𝐵)\)</span>是不是等于2。</li></ul></li></ul></li></ul><h2 id="first-fit-decreasing-algorithm">First-Fit-Decreasingalgorithm</h2><ul><li><strong>idea</strong>:将物品按size从大到小排序,依次进行装箱,逐个检查当前已经开着的箱子,发现第一个能装下它的箱子就装。如果都装不下,开一个新的箱子装它。</li><li><strong>performance guarantee</strong>:<spanclass="math inline">\(F F D(I) \leq\left(\frac{11}{9}\right)\operatorname{OPT}(I)+4\)</span></li></ul><h2 id="first--fit-algorithm">First- Fit algorithm</h2><ul><li><p><strong>idea</strong>:将物品依次进行装箱,逐个检查当前已经开着的箱子,发现第一个能装下它的箱子就装。如果都装不下,开一个新的箱子装它。</p></li><li><p><strong>performance</strong>: <spanclass="math inline">\(\mathrm{FF}(I)=\ell \leq 2\operatorname{SIZE}(I)+1 \leq 2 \operatorname{OPT}(I)+1\)</span>.</p><ul><li><p><span class="math inline">\(proof\)</span>:</p><ul><li><p>把编号相邻的箱子配对, 考虑箱子<spanclass="math inline">\(2k−1\)</span>和箱子<spanclass="math inline">\(2k\)</span>。我们打开了箱子<spanclass="math inline">\(2k\)</span>, 说明箱子<spanclass="math inline">\(2k−1\)</span>里面的物品体积之和加上箱子<spanclass="math inline">\(2k\)</span>里面的第一个物品的体积,必然是大于1的,否则按照算法流程会把那个物品放入箱子<spanclass="math inline">\(2k−1\)</span>.</p></li><li><p>设加入最后一个箱子的第一件物品为<spanclass="math inline">\(L\)</span>,<strong><spanclass="math inline">\(\sum_{i=1}^{L-1}a_i>\left\lfloor\frac{\ell}{2}\right\rfloor\)</span></strong>。因此<spanclass="math inline">\(SIZE(I)=\sum_{i=1}^{n} a_i \geq \sum_{i=1}^{L-1}a_i>\left\lfloor\frac{\ell}{2}\right\rfloor\geq\frac{\ell-1}{2}\)</span>.</p></li><li><p>显然,<span class="math inline">\(OPT(I)\geqSIZE(I)\)</span>,因为当所有箱子完全装满时<spanclass="math inline">\(OPT(I)= SIZE(I)\)</span>。</p></li><li><p>综上得到<span class="math inline">\(\mathrm{FF}(I)=\ell\leq 2\operatorname{OPT}(I)+1\)</span>.</p></li></ul></li></ul></li><li><p><imgsrc="../images/The-bin-packing-problem/image-20230109053203159.png" /></p></li></ul><h2 id="dynamic-programming-algorithm">dynamic programmingalgorithm</h2><ul><li><p><strong>special case 1</strong>: constant number of distinctpiece sizes, only a constant number of pieces can fit into onebin.?</p></li><li><p><imgsrc="../images/The-bin-packing-problem/image-20230109060722121.png" /></p><ul><li><p><span class="math inline">\(proof\)</span>:</p><ul><li><p>begin with small pieces:<spanclass="math inline">\(\ell\)</span></p></li><li><p>otherwise:已知所有的物品的<span class="math inline">\(a_i >\gamma\)</span>,则除最后一个箱子外,任一箱内的物品体积之和为<spanclass="math inline">\(1-\gamma\)</span>,否则还可以继续装物品。设总共装了<spanclass="math inline">\(K+1\)</span>个箱子,则<spanclass="math inline">\(SIZE(I)\geq (1-\gamma)K\)</span>,<spanclass="math inline">\(K+1\leq SIZE(I)/1-\gamma\)</span>。</p></li></ul></li><li><p>为了设计出一种优于FF的算法,根据<span class="math inline">\(Lemma3.10\)</span>需要令<span class="math inline">\(\gamma =ϵ/2\)</span>。</p></li></ul></li><li><p><strong>Linear grouping scheme</strong></p><ul><li><strong>step1 分组</strong>: 已知实例<spanclass="math inline">\(I\)</span>、参数<spanclass="math inline">\(k\)</span>,对<spanclass="math inline">\(I\)</span>进行如下分组:第一组由<spanclass="math inline">\(k\)</span>个最大的物品组成,第二组由剩下物品中<spanclass="math inline">\(k\)</span>个最大的物品组成......直至所有物品都被分组。最后一组由<spanclass="math inline">\(h\)</span>个物品组成,<spanclass="math inline">\(h \leq k\)</span>。</li><li><strong>step2凑整</strong>:丢掉第一组,将各组中的物品变为该组中最大物品的大小。</li><li><imgsrc="../images/The-bin-packing-problem/image-20230109064537643.png" /></li><li><imgsrc="../images/The-bin-packing-problem/image-20230109071159326.png" /></li><li><span class="math inline">\(proof\)</span>:<ul><li>由于<span class="math inline">\(I\)</span>中的第一组永远大于<spanclass="math inline">\(I'\)</span>第一组中的物品,以此类推...所以<spanclass="math inline">\(OPT(I')\leq OPT(I)\)</span>。</li><li>将<span class="math inline">\(I\)</span>中<spanclass="math inline">\(k\)</span>个最大的物品单独放在<spanclass="math inline">\(k\)</span>个箱子中,剩余的物品因为总的来说小于<spanclass="math inline">\(I'\)</span>中的物品,所以满足<spanclass="math inline">\(OPT(I)\leq OPT(I')+k\)</span>。</li></ul></li></ul></li><li><p><strong>asymptotic polynomial-time approximationscheme</strong></p><ul><li><p><imgsrc="../images/The-bin-packing-problem/image-20230109073535089.png" /></p></li><li><p><strong>analysis</strong>:</p></li><li><p><imgsrc="../images/The-bin-packing-problem/image-20230109073818555.png" /></p><ul><li><p><span class="math inline">\(proof\)</span>:</p><ul><li><p>已知该算法最多需要${,(1+ϵ)OPT(I)+1} $个箱子</p></li><li><p>由<span class="math inline">\(Lemma 3.11\)</span>,<spanclass="math inline">\(OPT(I')\leq OPT(I)\)</span>,又因为<spanclass="math inline">\(k=\lfloor\epsilonSIZE(I)\rfloor\)</span></p></li><li><p><span class="math display">\[\begin{aligned}\text { result } & \leq \max \left\{O PT\left(I^{\prime}\right)+k,(1+\epsilon) O P T+1\right\} \\& \leq \max \{O P T(I)+k,(1+\epsilon) O P T+1\} \\& \leq \max \{O P T(I)+\lfloor\epsilon S I Z E\rfloor,(1+\epsilon) OP T+1\} \\& \leq \max \{O P T(I)+\epsilon O P T,(1+\epsilon) O P T+1\} \\& \leq \max \{(1+\epsilon) O P T,(1+\epsilon) O P T+1\}\end{aligned}\]</span></p></li></ul></li></ul></li></ul></li></ul>]]></content>
<categories>
<category> 运筹 </category>
<category> 近似算法 </category>
</categories>
<tags>
<tag> 近似算法 </tag>
<tag> Bin-Packing </tag>
</tags>
</entry>
<entry>
<title>动态网页爬取</title>
<link href="/post/298cb32d.html"/>
<url>/post/298cb32d.html</url>
<content type="html"><![CDATA[<h1 id="静态网页与动态网页的区别">静态网页与动态网页的区别</h1><ul><li>URL是什么?</li></ul><p>http://www.php.cn/article.html</p><p>此链接叫做URL,统一资源定位符,全球性地址,用于定位网上的资源。</p><ul><li>静态网页</li></ul><p>静态网页每个网页中都有一个固定的URL,网页URL以htm、HTML、shtml等常见形式为后缀,而且不含有问号</p><p>网页内容一经发布到网页服务器上,无论是否有用户访问,每个静态网页的内容都是保存在网站服务器上的。也就是说静态网页是实实在在保存在服务器上的文件,每个网页都是一个独立的文件,内容相对稳定,交互性较差;</p><p>动态网页以数据库技术为基础,可以大大降低网站维护的工作量,采用动态网页技术的网站,可以实现更多的功能,如用户注册,用户登录,在线调查等;</p><p>动态网页实际上并不是独立存在于服务器上的网页文件,只有当用户请求时,服务器才会返回一个完整的网页,动态网页的问号对搜索引擎检索存在一定的问题,因此使用动态的网站使用搜索引擎时需要一定的技术才能适应搜索引擎的要求;</p><p><strong>查看浏览器执行JavaScript之后生成的HTML源码。(F12或者打开开发者工具)</strong></p><p><strong>网页中搜索的快捷键(command+f)</strong></p><h1 id="逆向分析爬取动态网页">逆向分析爬取动态网页</h1><p>XHR是Ajax中的概念,表示XML-HTTP-request,一般Javascript加载的文件隐藏在JS或者XHR。</p><p>因此可以根据请求在URL中爬取信息</p><p>依次点击:<code>XHR</code>-><code>“/bookinfo”</code>-><code>Headers</code>->找到“RequestURL”信息,如图所示。</p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221024222556458.png"alt="image-20221024222556458" /><figcaption aria-hidden="true">image-20221024222556458</figcaption></figure><p>实例:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line">url = <span class="string">'http://www.ptpress.com.cn/bookinfo/getBookListForWS'</span></span><br><span class="line">return_data = requests.get(url).text</span><br><span class="line">data = json.loads(return_data)</span><br><span class="line">news = data[<span class="string">'data'</span>]</span><br><span class="line"><span class="keyword">for</span> n <span class="keyword">in</span> news:</span><br><span class="line"> bookName = n[<span class="string">'bookName'</span>]</span><br><span class="line"> author = n[<span class="string">'author'</span>]</span><br><span class="line"> price = n[<span class="string">'price'</span>]</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"新书名:"</span>,bookName,<span class="string">'\n'</span>,<span class="string">"作者:"</span>,author,<span class="string">'\n'</span>,<span class="string">"价格:"</span>,price)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'\n'</span>)</span><br></pre></td></tr></table></figure><h1 id="使用selenium库爬取动态网页">使用Selenium库爬取动态网页</h1><p>https://home.cnblogs.com/u/qq-2780619724/</p><ul><li>driver的基本操作</li></ul><p><em>WebDriverWait(driver,</em> <em>等待时间)</em></p><p>指定某个条件,然后设置最长等待时间。如果在这个时间还没有找到元素,那么便会抛出异常,在登录“http://www.ptpress.com.cn/search/books”网页等待10秒。</p><p>WebDriverWait函数是默认每500毫秒调用一次ExpectedCondition,直到成功返回。ExpectedCondition的成功返回类型是布尔值,对于所有其他ExpectedCondition类型,则返回True或非Null返回值。如果在10秒内可能发现元素返回,就会在抛出TimeoutException异常。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#创建webdriver对象</span></span><br><span class="line">driver = webdriver.Chrome()</span><br><span class="line"><span class="comment">#等待变量</span></span><br><span class="line">wait = WebDriverWait(driver,<span class="number">10</span>)</span><br></pre></td></tr></table></figure><p><em>对WebDriver对象的操作</em></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#创建webdriver对象</span></span><br><span class="line">driver = webdriver.Chrome()</span><br><span class="line"><span class="comment">#等待变量</span></span><br><span class="line">wait = WebDriverWait(driver,<span class="number">10</span>)</span><br><span class="line"><span class="comment">#打开网页</span></span><br><span class="line">driver.get(<span class="string">"http://www.ptpress.com.cn/search/books"</span>)</span><br><span class="line"><span class="comment">#获取网页源码</span></span><br><span class="line">data = driver.page_source</span><br><span class="line"><span class="comment">#确认元素是否可单击</span></span><br><span class="line">confirm_btn = wait.until(EC.element_to_be_clickable(</span><br><span class="line">(By.CSS_SELECTOR,<span class="string">'#app>div:nth-child(1)>div>div>div>button>i'</span>)))</span><br><span class="line"><span class="comment">#关闭webdriver对象</span></span><br><span class="line">driver.quit()</span><br></pre></td></tr></table></figure><ul><li>元素定位法</li></ul><p>HTML表单包含了表单元素,而表单元素指的是丌同类型的input元素、复选框、单选按钮、提交按钮等。</p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026095346482.png"alt="image-20221026095346482" /><figcaption aria-hidden="true">image-20221026095346482</figcaption></figure><p>Selenium库的find_element的语法使用格式如下。</p><p><strong><em>driver.find_element_by_id(By.method,‘selector_url’)</em></strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#实例</span></span><br><span class="line"><span class="keyword">from</span> selenium <span class="keyword">import</span> webdriver</span><br><span class="line">browser = webdriver.Chrome()</span><br><span class="line">browser.get(<span class="string">"http://www.ptpress.com.cn/search/books"</span>)</span><br><span class="line">input_first = browser.find_element(By.ID,<span class="string">"searchVal"</span>)<span class="comment">#element</span></span><br><span class="line">input_second = browser.find_element(By.CSS_SELECTOR,<span class="string">"#searchVal"</span>)<span class="comment">#selector</span></span><br><span class="line">input_third = browser.find_element(By.XPATH,<span class="string">'//*[@id="searchVal"]'</span>)<span class="comment">#Xpath</span></span><br><span class="line"><span class="built_in">print</span>(input_first)</span><br><span class="line"><span class="built_in">print</span>(input_second)</span><br><span class="line"><span class="built_in">print</span>(input_third)</span><br><span class="line">browser.close()</span><br></pre></td></tr></table></figure><p>1 <strong>css_selector定位元素</strong></p><p>step1:<code>F12</code> 找到对应搜索按键的源码</p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026085421698.png"alt="image-20221026085421698" /><figcaption aria-hidden="true">image-20221026085421698</figcaption></figure><p>step2:<code>右键</code>-><code>copy</code>-><code>Copy selector</code></p><p>step3:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#实例 确认元素是否可以单击</span></span><br><span class="line">confirm_btn = wait.until(EC.element_to_be_clickable(</span><br><span class="line">(By.CSS_SELECTOR,<span class="string">'#app>div:nth-child(1)>div>div>div>button>i'</span>)))</span><br></pre></td></tr></table></figure><p>2 <strong>xpath 定位元素</strong>( 一般都不用完整的xpath路径 )</p><p><code>右键</code>-><code>copy</code>-><code>Copy Xpath</code></p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026090740655.png"alt="image-20221026090740655" /><figcaption aria-hidden="true">image-20221026090740655</figcaption></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">input_third = browser.find_element(By.XPATH,<span class="string">'//*[@id="searchVal"]'</span>)</span><br></pre></td></tr></table></figure><ul><li>选择浏览器的不同选项标签,打开不同的网页</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> selenium <span class="keyword">import</span> webdriver</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line">browser = webdriver.Chrome()</span><br><span class="line">browser.get(<span class="string">'http://www.ptpress.com.cn/search/books'</span>)</span><br><span class="line"><span class="comment">#同步执行,()内为Javascript代码,实现窗口打开</span></span><br><span class="line">browser.execute_script(<span class="string">'window.open()'</span>)</span><br><span class="line"><span class="built_in">print</span>(browser.window_handles)</span><br><span class="line"><span class="comment">#此时的页面还没有转换,browser.window_handles中含两个元素,分别是两个网页</span></span><br><span class="line">browser.switch_to.window(browser.window_handles[<span class="number">1</span>])</span><br><span class="line">browser.get(<span class="string">'http://www.tipdm.com'</span>)</span><br><span class="line"><span class="comment">#运行完上行代码后才开始跳转到另一网页</span></span><br><span class="line">time.sleep(<span class="number">1</span>)</span><br><span class="line">browser.switch_to.window(browser.window_handles[<span class="number">0</span>])</span><br><span class="line"><span class="comment">#运行完上行代码后返回之前网页,但是新网页未关闭</span></span><br><span class="line">browser.get(<span class="string">'http://www.tipdm.org'</span>)</span><br><span class="line"><span class="comment">#运行完上行代码后第一个网页变化</span></span><br></pre></td></tr></table></figure><ul><li>自动点击搜索按钮</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> selenium <span class="keyword">import</span> webdriver</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.common.by <span class="keyword">import</span> By</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.support.ui <span class="keyword">import</span> WebDriverWait</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.support <span class="keyword">import</span> expected_conditions <span class="keyword">as</span> EC</span><br><span class="line">driver = webdriver.Chrome()</span><br><span class="line">driver.get(<span class="string">'http://www.ptpress.com.cn/search/books'</span>)</span><br><span class="line">wait = WebDriverWait(driver,<span class="number">10</span>)</span><br><span class="line"><span class="comment">#等待确认按钮加载完成</span></span><br><span class="line">search_btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,</span><br><span class="line"><span class="string">'#app > div:nth-child(1) > div > div > div > button > i'</span>)))</span><br><span class="line"><span class="comment">#单击搜索</span></span><br><span class="line">search_btn.click()</span><br></pre></td></tr></table></figure><ul><li>执行JavaScript</li></ul><p>实例:Selenium库中的execute_script方法能够直接调用JavaScript方法来实现翻页到底部、弹框等操作。比如在“http://www.ptpress.com.cn/search/books”网页中用JavaScript翻到页面底部,并弹框提示爬虫</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> selenium <span class="keyword">import</span> webdriver</span><br><span class="line">browser = webdriver.Chrome()</span><br><span class="line">browser.get(<span class="string">"http://www.ptpress.com.cn/search/books"</span>)</span><br><span class="line"><span class="comment">#翻到底页</span></span><br><span class="line">browser.execute_script(<span class="string">'window.scrollTo(0, document.body.scrollHeight)'</span>)</span><br><span class="line">browser.execute_script(<span class="string">'alert("python爬虫")'</span>)</span><br></pre></td></tr></table></figure><ul><li>判断的条件</li></ul><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026101646096.png"alt="image-20221026101646096" /><figcaption aria-hidden="true">image-20221026101646096</figcaption></figure><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026101704924.png"alt="image-20221026101704924" /><figcaption aria-hidden="true">image-20221026101704924</figcaption></figure><h2id="实例1在搜索页面-搜索-python编程爬取网页提取图书信息">实例1:<strong>在搜索页面搜索 “python编程”,爬取网页,提取图书信息</strong></h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> selenium <span class="keyword">import</span> webdriver</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.common.by <span class="keyword">import</span> By</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.support.ui <span class="keyword">import</span> WebDriverWait</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.support <span class="keyword">import</span> expected_conditions <span class="keyword">as</span> EC</span><br><span class="line"><span class="keyword">from</span> bs4 <span class="keyword">import</span> BeautifulSoup</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="comment">#创建webdriver对象</span></span><br><span class="line">driver = webdriver.Chrome()</span><br><span class="line"><span class="comment">#等待变量</span></span><br><span class="line">wait = WebDriverWait(driver,<span class="number">10</span>)</span><br><span class="line"><span class="comment">#模拟搜索"python编程〞</span></span><br><span class="line"><span class="comment">#(1)打开网页</span></span><br><span class="line">driver.get(<span class="string">"http://www.ptpress.com.cn/search/books"</span>)</span><br><span class="line"><span class="comment">#(2)等待〝搜素〞按钮加载完成,确认元素是否已经出现,在搜索框填写 〝python 编程〞</span></span><br><span class="line"><span class="built_in">input</span> = wait.until(EC.element_to_be_clickable((By.ID,<span class="string">"searchVal"</span>)))</span><br><span class="line">search_btn = driver.find_element(By.ID,<span class="string">"searchVal"</span>)</span><br><span class="line"><span class="comment">#等待5秒 只是用于程序清楚演示</span></span><br><span class="line">time.sleep(<span class="number">5</span>)</span><br><span class="line">search_btn.send_keys(<span class="string">'python编程'</span>)</span><br><span class="line"><span class="comment">#(3)等待“确认”按钮是否出现,单击“确认”按钮</span></span><br><span class="line">confirm_btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,</span><br><span class="line"> <span class="string">'#app>div:nth-child(1)>div>div>div>button>i'</span>)))</span><br><span class="line"><span class="comment">#等待5秒,等待新网页载入</span></span><br><span class="line">time.sleep(<span class="number">5</span>)</span><br><span class="line">confirm_btn.click()</span><br><span class="line"><span class="comment">#等待5秒,等待新网页载入</span></span><br><span class="line">time.sleep(<span class="number">5</span>)</span><br><span class="line"><span class="comment">#(4)获取新网页源码</span></span><br><span class="line">html = driver.page_source</span><br><span class="line"><span class="comment">#(5)使用BeautifulSoup找到书籍信息的模块</span></span><br><span class="line">soup = BeautifulSoup(html,<span class="string">'lxml'</span>)</span><br><span class="line">a = soup.select(<span class="string">'.rows'</span>)</span><br><span class="line"><span class="comment">##使用正则表达式解析书籍图片信息</span></span><br><span class="line">lsl = <span class="string">'< img src="(.*?)"/></div>'</span></span><br><span class="line">pattern = re.<span class="built_in">compile</span>(lsl,re.S)</span><br><span class="line">res_img = re.findall(pattern,<span class="built_in">str</span>(a))</span><br><span class="line"><span class="comment">#使用正则表达式解析书籍文字信息</span></span><br><span class="line"><span class="comment">#ls2 = '< img src=".*?"/></div>.*?<p>(.*?)</p ></a >'</span></span><br><span class="line">ls2 = <span class="string">'< img src=".*?"/></div>.*?<p>(.*?)</p ></a >'</span></span><br><span class="line">pattern2 = re.<span class="built_in">compile</span>(ls2,re.S)</span><br><span class="line">res_text = re.findall(pattern2,<span class="built_in">str</span>(a))</span><br><span class="line"><span class="built_in">print</span> (res_text)</span><br><span class="line"><span class="built_in">print</span> (res_img)</span><br><span class="line">driver.close()</span><br></pre></td></tr></table></figure><ul><li>BeautifulSoup解析书籍信息的细节</li></ul><p><strong>step1</strong>:获取新网页源码,生成BeautifulSoup对象</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">html = driver.page_source</span><br><span class="line">soup = BeautifulSoup(html,<span class="string">'lxml'</span>)</span><br></pre></td></tr></table></figure><p><strong>step2</strong>:查找soup中书籍的信息(提取名为rows的class)</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">a = soup.select(<span class="string">'.rows'</span>)</span><br></pre></td></tr></table></figure><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026140039702.png"alt="image-20221026140039702" /><figcaption aria-hidden="true">image-20221026140039702</figcaption></figure><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026140101850.png"alt="image-20221026140101850" /><figcaption aria-hidden="true">image-20221026140101850</figcaption></figure><p><strong>step3</strong>:使用正则表达式解析书籍图片信息</p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026141123064.png"alt="image-20221026141123064" /><figcaption aria-hidden="true">image-20221026141123064</figcaption></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">lsl = <span class="string">r'<img src="(.*?)"/>'</span></span><br><span class="line">pattern = re.<span class="built_in">compile</span>(lsl,re.S)</span><br><span class="line">res_img = re.findall(pattern,<span class="built_in">str</span>(a))</span><br><span class="line"><span class="built_in">print</span> (res_img)</span><br></pre></td></tr></table></figure><p><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026140950361.png" /></p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026143502922.png"alt="image-20221026143502922" /><figcaption aria-hidden="true">image-20221026143502922</figcaption></figure><p><code>complie(String regex)</code>:创建一个正则表达式对象;</p><p><code>re.S</code>参数,正则表达式会将这个字符串作为一个整体,在整体中进行匹配;</p><p><strong>step4</strong>:使用正则表达式解析书籍文字信息</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ls2 = <span class="string">r'<p>(.*?)</p>'</span></span><br><span class="line">pattern2 = re.<span class="built_in">compile</span>(ls2,re.S)</span><br><span class="line">res_text = re.findall(pattern2,<span class="built_in">str</span>(a))</span><br><span class="line"><span class="built_in">print</span> (res_text)</span><br></pre></td></tr></table></figure><h2id="实例2使用selenium-采集httpwww.tup.tsinghua.edu.cnindex.html的图书名称">实例2:使用selenium采集http://www.tup.tsinghua.edu.cn/index.html的图书名称</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> selenium <span class="keyword">import</span> webdriver</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.common.by <span class="keyword">import</span> By</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.support.ui <span class="keyword">import</span> WebDriverWait</span><br><span class="line"><span class="keyword">from</span> selenium.webdriver.support <span class="keyword">import</span> expected_conditions <span class="keyword">as</span> EC</span><br><span class="line"><span class="keyword">from</span> bs4 <span class="keyword">import</span> BeautifulSoup</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="comment">#创建webdriver对象</span></span><br><span class="line">driver = webdriver.Chrome()</span><br><span class="line"><span class="comment">#等待变量</span></span><br><span class="line">wait = WebDriverWait(driver,<span class="number">10</span>)</span><br><span class="line"><span class="comment">#模拟搜索"python编程〞</span></span><br><span class="line"><span class="comment">#(1)打开网页</span></span><br><span class="line">driver.get(<span class="string">"http://www.tup.tsinghua.edu.cn/index.html"</span>)</span><br><span class="line"><span class="comment">#(2)等待〝搜素〞按钮加载完成,确认元素是否已经出现,在搜索框填写 〝python 编程〞</span></span><br><span class="line"><span class="built_in">input</span> = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,<span class="string">'body > div.nav > div.logo > div.logo2 > div > div.logo22-4 > input[type=image]'</span>)))</span><br><span class="line">search_btn = driver.find_element(By.ID,<span class="string">"input_key"</span>)</span><br><span class="line"><span class="comment">#等待5秒 只是用于程序清楚演示</span></span><br><span class="line">time.sleep(<span class="number">5</span>)</span><br><span class="line">search_btn.send_keys(<span class="string">'python'</span>)</span><br><span class="line"><span class="comment">#(3)等待“确认”按钮是否出现,单击“确认”按钮</span></span><br><span class="line">confirm_btn = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,<span class="string">'body > div.nav > div.logo > div.logo2 > div > div.logo22-4'</span>)))</span><br><span class="line"><span class="comment">#等待5秒,等待新网页载入</span></span><br><span class="line">time.sleep(<span class="number">5</span>)</span><br><span class="line">confirm_btn.click()</span><br><span class="line"><span class="comment">#等待5秒,等待新网页载入</span></span><br><span class="line">time.sleep(<span class="number">5</span>)</span><br><span class="line"><span class="comment">#(4)获取新网页源码</span></span><br><span class="line">driver.switch_to.window(driver.window_handles[<span class="number">1</span>])</span><br><span class="line">html = driver.page_source</span><br><span class="line"><span class="comment">#(5)使用BeautifulSoup找到书籍信息的模块</span></span><br><span class="line">soup = BeautifulSoup(html,<span class="string">'lxml'</span>)</span><br><span class="line">a = soup.select(<span class="string">'span'</span>)</span><br><span class="line"><span class="built_in">print</span> (<span class="built_in">str</span>(a)) </span><br><span class="line">ls2=<span class="string">r'<span title="(.*?)">.*?</span>'</span></span><br><span class="line">pattern2=re.<span class="built_in">compile</span>(ls2, re.S)</span><br><span class="line">res_text=re.findall(pattern2, <span class="built_in">str</span>(a))</span><br><span class="line"><span class="built_in">print</span> (res_text)</span><br><span class="line">res_text_str=<span class="string">"; "</span>.join(res_text)</span><br><span class="line"><span class="built_in">print</span> (res_text_str)</span><br><span class="line">driver.execute_script(<span class="string">'alert("查询到图书:'</span>+res_text_str+<span class="string">'")'</span>)</span><br><span class="line">time.sleep(<span class="number">5</span>)</span><br><span class="line"><span class="comment">#driver.close()</span></span><br></pre></td></tr></table></figure><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026151815882.png"alt="image-20221026151815882" /><figcaption aria-hidden="true">image-20221026151815882</figcaption></figure><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026151857589.png"alt="image-20221026151857589" /><figcaption aria-hidden="true">image-20221026151857589</figcaption></figure><h1 id="解析网页">解析网页</h1><h2 id="使用chrome开发者工具查看网页">使用chrome开发者工具查看网页</h2><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026105503799.png"alt="image-20221026105503799" /><figcaption aria-hidden="true">image-20221026105503799</figcaption></figure><ul><li>元素面板</li></ul><p>依次单击树状结构的三角符号,依次打开“body”“header”“div”“nav”标签,找到第一个“li”标签,如图所示。</p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026110405001.png"alt="image-20221026110405001" /><figcaption aria-hidden="true">image-20221026110405001</figcaption></figure><ul><li>源代码面板</li></ul><p>切换至源代码面板(Sources),单击左侧“tipdm”文件夹中的“index.html”文件,将在中间显示其包含的完整代码,如图所示。</p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026110551546.png"alt="image-20221026110551546" /><figcaption aria-hidden="true">image-20221026110551546</figcaption></figure><ul><li>网络面板</li></ul><p>切换至网络面板(Network),需先重新加载页面,之后单击“index.html”资源,将在中间显示该资源的头部信息、预览、响应信息、Cookies和花费时间详情,如图所示。</p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026122519047.png"alt="image-20221026122519047" /><figcaption aria-hidden="true">image-20221026122519047</figcaption></figure><p>1)Headers标签展示该资源的<strong>HTTP头信息</strong>,主要包括RequestURL、Request Method、Status Code、RemoteAddress等基本信息,以及详细的Response Headers、Request Headers。</p><p>2)Preview标签根据所选择的资源类型(JSON、图片、文本)显示相应的<strong>预览</strong>。</p><p>3)Response标签显示HTTP的响应信息,如图所示中选中的“index.html”文件为HTML文件,将<strong>展示HTML代码</strong>。</p><p>4)Cookies标签显示资源<strong>HTTP的请求和响应过程中的Cookies信息</strong>。</p><p>5)Timing标签显示资源在<strong>整个请求过程中各部分花费的时间</strong>。</p><h2 id="用正则表达式解析网页">用正则表达式解析网页</h2><h3 id="python正则表达式的re模块">Python正则表达式的re模块</h3><p>先将正则表达式的字符串形式编译为Pattern实例;然后使用Pattern实例处理文本并获得匹配结果(一个Match实例);最后使用Match实例获得信息,迚行其他的操作。</p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026123537774.png"alt="image-20221026123537774" /><figcaption aria-hidden="true">image-20221026123537774</figcaption></figure><ul><li><strong>compile方法</strong></li></ul><p><em>re.compile(string[,flag])</em></p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026125147594.png"alt="image-20221026125147594" /><figcaption aria-hidden="true">image-20221026125147594</figcaption></figure><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026125218623.png"alt="image-20221026125218623" /><figcaption aria-hidden="true">image-20221026125218623</figcaption></figure><ul><li><strong>search方法</strong></li></ul><p><em>re.search(pattern,string[,flags])</em></p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026125457513.png"alt="image-20221026125457513" /><figcaption aria-hidden="true">image-20221026125457513</figcaption></figure><ul><li><strong>findall方法</strong></li></ul><p><em>re.findall(pattern,string[,flags])</em></p><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026125702448.png"alt="image-20221026125702448" /><figcaption aria-hidden="true">image-20221026125702448</figcaption></figure><h3 id="使用xpath解析网页">使用Xpath解析网页</h3><p>P38</p><h3 id="使用beautiful-soup解析网页">使用Beautiful Soup解析网页</h3><figure><imgsrc="../images/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E7%88%AC%E5%8F%96/image-20221026130313644.png"alt="image-20221026130313644" /><figcaption aria-hidden="true">image-20221026130313644</figcaption></figure><ul><li><strong>创建BeautifulSoup对象</strong></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">soup = BeautifulSoup(html,<span class="string">'lxml'</span>)</span><br></pre></td></tr></table></figure><ul><li>对象类型</li></ul><p>1)<strong>Tag对象类型</strong></p><p>HTML中的一个个标签,有两个重要的属性,是 name 和 attrs,例如:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> bs4 <span class="keyword">import</span> BeautifulSoup </span><br><span class="line">file = <span class="built_in">open</span>(<span class="string">'./aa.html'</span>, <span class="string">'rb'</span>) </span><br><span class="line">html = file.read() </span><br><span class="line">bs = BeautifulSoup(html,<span class="string">"html.parser"</span>) </span><br><span class="line"><span class="comment"># 获取title标签的所有内容</span></span><br><span class="line"><span class="built_in">print</span>(bs.title) </span><br><span class="line"><span class="comment"># 获取head标签的所有内容</span></span><br><span class="line"><span class="built_in">print</span>(bs.head) </span><br><span class="line"><span class="comment"># 获取第一个a标签的所有内容</span></span><br><span class="line"><span class="built_in">print</span>(bs.a) </span><br><span class="line"><span class="comment"># 类型</span></span><br><span class="line"><span class="built_in">print</span>(<span class="built_in">type</span>(bs.a))</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> bs4 <span class="keyword">import</span> BeautifulSoup </span><br><span class="line">file = <span class="built_in">open</span>(<span class="string">'./aa.html'</span>, <span class="string">'rb'</span>) </span><br><span class="line">html = file.read() </span><br><span class="line">bs = BeautifulSoup(html,<span class="string">"html.parser"</span>) </span><br><span class="line"><span class="comment"># [document] #bs 对象本身比较特殊,它的 name 即为 [document]</span></span><br><span class="line"><span class="built_in">print</span>(bs.name) </span><br><span class="line"><span class="comment"># head #对于其他内部标签,输出的值便为标签本身的名称</span></span><br><span class="line"><span class="built_in">print</span>(bs.head.name) </span><br><span class="line"><span class="comment"># 在这里,我们把 a 标签的所有属性打印输出了出来,得到的类型是一个字典。</span></span><br><span class="line"><span class="built_in">print</span>(bs.a.attrs) </span><br><span class="line"><span class="comment">#还可以利用get方法,传入属性的名称,二者是等价的</span></span><br><span class="line"><span class="built_in">print</span>(bs.a[<span class="string">'class'</span>]) <span class="comment"># 等价 bs.a.get('class')</span></span><br><span class="line"><span class="comment"># 可以对这些属性和内容等等进行修改</span></span><br><span class="line">bs.a[<span class="string">'class'</span>] = <span class="string">"newClass"</span></span><br><span class="line"><span class="built_in">print</span>(bs.a) </span><br><span class="line"><span class="comment"># 还可以对这个属性进行删除</span></span><br><span class="line"><span class="keyword">del</span> bs.a[<span class="string">'class'</span>] </span><br><span class="line"><span class="built_in">print</span>(bs.a)</span><br></pre></td></tr></table></figure><p>2)<strong>NavigableString对象类型</strong></p><p>已经得到了标签的内容,获取标签内部的文字</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">bs = BeautifulSoup(html,<span class="string">"html.parser"</span>)</span><br><span class="line"> </span><br><span class="line"><span class="built_in">print</span>(bs.title.string) </span><br><span class="line"><span class="built_in">print</span>(<span class="built_in">type</span>(bs.title.string))</span><br></pre></td></tr></table></figure><p>3)<strong>BeautifulSoup对象类型</strong></p><p>BeautifulSoup对象表示的是一个文档的内容。大部分时候,可以把它当作 Tag对象,是一个特殊的 Tag,我们可以分别获取它的类型,名称,以及属性</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> bs4 <span class="keyword">import</span> BeautifulSoup </span><br><span class="line">file = <span class="built_in">open</span>(<span class="string">'./aa.html'</span>, <span class="string">'rb'</span>) </span><br><span class="line">html = file.read()</span><br><span class="line"> </span><br><span class="line">bs = BeautifulSoup(html,<span class="string">"html.parser"</span>) </span><br><span class="line"><span class="built_in">print</span>(<span class="built_in">type</span>(bs.name)) </span><br><span class="line"><span class="built_in">print</span>(bs.name) </span><br><span class="line"><span class="built_in">print</span>(bs.attrs)</span><br></pre></td></tr></table></figure><p>4)<strong>Comment对象类型</strong></p><p>Comment 对象是一个特殊类型的 NavigableString对象,其输出的内容不包括注释符号。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> bs4 <span class="keyword">import</span> BeautifulSoup </span><br><span class="line">file = <span class="built_in">open</span>(<span class="string">'./aa.html'</span>, <span class="string">'rb'</span>) </span><br><span class="line">html = file.read() </span><br><span class="line">bs = BeautifulSoup(html,<span class="string">"html.parser"</span>) </span><br><span class="line"><span class="built_in">print</span>(bs.a)</span><br><span class="line"><span class="comment"># 此时不能出现空格和换行符,a标签如下:</span></span><br><span class="line"><span class="comment"># <a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!--新闻--></a></span></span><br><span class="line"><span class="built_in">print</span>(bs.a.string) <span class="comment"># 新闻</span></span><br><span class="line"><span class="built_in">print</span>(<span class="built_in">type</span>(bs.a.string)) <span class="comment"># <class 'bs4.element.Comment'></span></span><br></pre></td></tr></table></figure><ul><li>其他的函数</li></ul><p>*select(self, selector, namespaces=None, limit=None, **kwargs)*</p><p>在写 CSS 时,标签名不加任何修饰,类名前加点,id名前加#,在这里我们也可以利用类似的方法来筛选元素,用到的方法是soup.select()。</p><p><strong>功能</strong>:查找html中我们所需要的内容</p><p><strong>selector</strong>:"包含CSS选择器的字符串"</p><p>1)通过(HTML)标签名查找</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">print</span>(soup.select(<span class="string">'title'</span>))</span><br><span class="line"><span class="built_in">print</span>(soup.select(<span class="string">'a'</span>))<span class="comment">#输出的列表含有多个包含标签<a>的元素</span></span><br></pre></td></tr></table></figure><p>2)通过CCS类<ahref="https://so.csdn.net/so/search?q=选择器&spm=1001.2101.3001.7020">选择器</a>查找</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">print</span>(soup.select(<span class="string">'.story'</span>))<span class="comment">#class的前面加.</span></span><br></pre></td></tr></table></figure><p>3)通过CCS id 选择器查找</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">print</span>(soup.select(<span class="string">'#link1'</span>))<span class="comment">#id前面加#</span></span><br></pre></td></tr></table></figure><p>4)组合查找</p><p>组合查找和通过标签名与类选择器、id选择器进行查找的组合原理是一样的,例如查找p 标签中,id 等于 link1的内容,二者需要用空格分开。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">print</span>(soup.select(<span class="string">'p #link1'</span>))</span><br></pre></td></tr></table></figure><p>5)子标签查找</p><p>父标签与子标签之间通过" > "表示递进关系</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">print</span>(soup.select(<span class="string">'p > b'</span>))</span><br></pre></td></tr></table></figure><p>6)通过属性查找</p><p>还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 通过href属性及其值进行查找</span></span><br><span class="line"><span class="built_in">print</span>(soup.select(<span class="string">'a[href="http://example.com/elsie"]'</span>))</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 编程 </category>
<category> python </category>
</categories>
<tags>
<tag> 爬虫 </tag>
<tag> python </tag>
</tags>
</entry>
<entry>
<title>java学习笔记</title>
<link href="/post/6cb5a254.html"/>
<url>/post/6cb5a254.html</url>
<content type="html"><![CDATA[<h1 id="第一章-java概述">第一章 Java概述</h1><h2 id="java语言的特点">Java语言的特点</h2><ol type="1"><li>强类型语言;没有指针;没有多重继承机制;自动无用内存回收机制(相比于C++,需要释放空间)</li><li>面向对象</li><li>跨平台 JVM(Java虚拟机,用来执行类文件,c++是不跨平台的)</li><li>解释编译两种运行方式(c++是编译型语言)</li></ol><h2 id="开发环境的搭建">开发环境的搭建</h2><ol type="1"><li>JVM、JRE、JDK</li><li>在命令行输入 javac命令进行测试</li></ol><p><ahref="https://image.baidu.com/search/detail?ct=503316480&z=undefined&tn=baiduimagedetail&ipn=d&word=JVM、JRE、JDK&step_word=&ie=utf-8&in=&cl=2&lm=-1&st=undefined&hd=undefined&latest=undefined&copyright=undefined&cs=1224667471,3927071967&os=2171360098,3000575419&simid=4090623277,771242609&pn=2&rn=1&di=7146857200093233153&ln=898&fr=&fmq=1666699282410_R&fm=&ic=undefined&s=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&is=0,0&istype=0&ist=&jit=&bdtype=0&spn=0&pi=0&gsm=1e0000000000001e&objurl=https%3A%2F%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttp%3A%2F%2Fwww.pianshen.com%2Fimages%2F862%2Fa08d9ee969fcaa90eededee0c0fbcb8e.png%26refer%3Dhttp%3A%2F%2Fwww.pianshen.com%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Dauto%3Fsec%3D1669291281%26t%3D350cf39061a9b9488c9762487bf7d7f3&rpstart=0&rpnum=0&adpicid=0&nojc=undefined&dyTabStr=MCw2LDQsNSwzLDEsNyw4LDIsOQ%3D%3D"><imgsrc="https://img2.baidu.com/it/u=257541335,1040751895&fm=253&fmt=auto&app=138&f=JPEG?w=934&h=480"alt="img" /></a></p><h2 id="java程序示例开发流程">Java程序示例开发流程</h2><ol type="1"><li><p>文件名和public类的名字相同</p></li><li><p>public static void main(String [] args){} 主方法/函数</p></li><li><p>javac HelloWorld.java运行程序文件.java得到一个字节码文件.class(在虚拟机中运行)javac.exe是编译器</p></li><li><p>java HellloWorld Java.exe是解释器</p></li><li><p>Java运行的是与机器无关的二进制格式的类文件</p></li></ol><h2 id="oop三大技术">OOP三大技术</h2><h3 id="封装">封装</h3><p>将对象的属性和实现细节隐藏起来,只给出如何使用这些信息。将数据(对象)及对数据的操作(方法)捆绑在一起称为类。</p><h3 id="继承">继承</h3><p>将一个已有类中的数据和方法保留,并加上自己特殊的数据和方法,从而构成一个新类。父类、子类。</p><h3 id="多态">多态</h3><p>在一个类或多个类中,可以让多个方法使用同一个名字,从而具有多态性。重载、覆盖。</p><h2 id="使用java核心api文档">使用Java核心API文档</h2><h2 id="面向对象技术">面向对象技术</h2><ol type="1"><li>类(学生)</li><li>对象/实例(张三、王五):类的某个特定实体</li><li>对象的两大属性(数据+方法)</li></ol><h1 id="第二章-数据表达式">第二章 数据表达式</h1><h2 id="基本语法元素">基本语法元素</h2><p><strong>空白</strong>:换行符、回车空格、水平定位键tab)、推格<em>注释<strong>:行内、多行、文档/</strong></em>/</p><p><strong>关键字</strong></p><p><strong>标识符</strong>:由字母、数字、下划线、美元符号组成,数字不能作为标识符的开头</p><p>Java源码使用unicode码</p><p><strong>编程风格</strong>:</p><p>类名或者接口名,每个单词首字母大写HelloWorld。</p><p>方法名:首字母小写,其余各单词首字母大写getName</p><p>常量名:字母全大写,单词之间_分割</p><p>变量名:规则同方法名</p><h2 id="基本数据类型">基本数据类型</h2><p><strong>基本数据类型</strong></p><p>整数类型 byte 8b short 16b int 32b long(长整型) 64b (有符号)</p><p>浮点数类型 float 单精度 32b double 双精度 64b</p><p>字符类型 char 16b</p><p>布尔类型boolean 8b</p><p><strong>复合数据类型</strong></p><h2 id="表达式">表达式</h2><p><strong>操作数</strong>:只有简单数据类型和String类型有常量形势</p><p><strong>变量</strong>:在方法内声明为局部变量/临时变量/栈变量;在类里面声明为成员变量</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a;</span><br><span class="line">String aa;</span><br></pre></td></tr></table></figure><p>对于简单变量,在声明后自动分配空间;对于引用变量,声明后只分配引用空间,new后才分配空间</p><p>由于Java是强类型语言,不支持变量类型自动任意转换,位数少的可以转换为位数多的</p><h1 id="第三章-流程控制语句重点">第三章 流程控制语句(重点)</h1><h2 id="java程序的结构">Java程序的结构</h2><p>一个<strong>Java程序</strong>由一个或多个<strong>.java文件</strong>组成。</p><p>每个<strong>.java</strong>文件由一个或多个<strong>接口或类</strong>组成,但最多<strong>只有一个public类</strong>,且文件名等于public类,<strong>大小写</strong>也要相同。</p><p>.java文件的构成要素:package语句、import语句、具有public权限的类定义、接口定义。</p><ul><li>Java包:包是类的容器,可以利用包来划分名字空间,避免类名冲突。不指定则默认无名包。不同包中的类可重名。packagepkg1;</li></ul><p>package必须是第一条非注释语句,且一个文件中最多只有一条package语句。</p><p>包的层次关系以小数点分隔,包可以包含包、文件。</p><p><strong>CLASSPATH</strong>可以搜寻包的路径。</p><p>类名是文件夹名,包名是文件夹名。</p><ul><li>引入语句</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//不导入包时</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MainPackage</span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span>{</span><br><span class="line"> pkg1.pkg2.pkg3.<span class="type">TestPackage</span> <span class="variable">test</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">pkg1</span>.pkg2.pkg3.TestPackage();</span><br><span class="line"> test.test();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="comment">//导入包时</span></span><br><span class="line"><span class="keyword">import</span> pkg1.pkg2.pkg3.*;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MainPackage</span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span>{</span><br><span class="line"> <span class="type">TestPackage</span> <span class="variable">test</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TestPackage</span>();</span><br><span class="line"> test.test();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="流程控制">流程控制</h2><p><strong>语句</strong>是Java的最小执行单元,以;作为分隔符。语句分为单语句、复合语句。</p><p>语句流有顺序流、分支流、循环流。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//赋值语句</span></span><br><span class="line">customer1 = <span class="keyword">new</span> <span class="title class_">Customer</span>();</span><br><span class="line"><span class="comment">//表达式语句</span></span><br><span class="line">x++;</span><br><span class="line"><span class="comment">//分支语句</span></span><br><span class="line"><span class="comment">//if语句 这里Java和c++有区别,Java的条件表达式必须得到一个逻辑值(boolean)不能是2,3....</span></span><br><span class="line"><span class="comment">//Java规定,else子句属于逻辑上离它最近的if语句</span></span><br><span class="line"><span class="keyword">if</span>(条件表达式)</span><br><span class="line"> 语句<span class="number">1</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line"> 语句<span class="number">2</span></span><br><span class="line"><span class="comment">//switch语句</span></span><br><span class="line"><span class="comment">//如果没有break会继续往下执行</span></span><br><span class="line"><span class="comment">//表达式的结果必须是int或者char</span></span><br><span class="line"><span class="type">int</span> <span class="variable">color</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line"><span class="keyword">switch</span>(color){</span><br><span class="line"> <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line"> System.out.println(<span class="string">"red"</span>);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line"> System.out.println(<span class="string">"green"</span>);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="number">3</span>:</span><br><span class="line"> System.out.println(<span class="string">"blue"</span>);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line">}</span><br><span class="line"><span class="comment">//跳转语句 Java抛弃了goto语句</span></span><br><span class="line"><span class="comment">//break语句 用于for while do语句 </span></span><br><span class="line"><span class="comment">//在块中和标号配合使用 格式:break 标号 用于从内层块跳到外层块</span></span><br><span class="line"><span class="comment">//ex:这样可以跳出两层循环</span></span><br><span class="line"><span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">20</span>;</span><br><span class="line">out: <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">2</span>;i<<span class="number">10</span>;i++){</span><br><span class="line"> System.out.println(<span class="string">"i="</span>+i);</span><br><span class="line"> <span class="keyword">while</span>(x<<span class="number">1000</span>){</span><br><span class="line">System.out.println(<span class="string">"i="</span>+i+<span class="string">",x="</span>+x);</span><br><span class="line"> <span class="keyword">if</span>(i*x>=<span class="number">80</span>) <span class="keyword">break</span> out;</span><br><span class="line"> <span class="keyword">else</span> x+=<span class="number">5</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="comment">//continue语句 用于结束当次循环,开始执行下一次循环</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="简单的输入输出">简单的输入/输出</h2><ul><li>Scanner类</li></ul><p>属于java.util包,方便读入不同类型的输入值。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//创建一个对象 输入的分隔符为空白</span></span><br><span class="line"><span class="comment">//next() 读入下一个对象,以字符串返回</span></span><br><span class="line"><span class="type">Scanner</span> <span class="variable">scan</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Scanner</span>(System.in);</span><br><span class="line"><span class="keyword">while</span>(<span class="literal">true</span>){</span><br><span class="line"> System.out.println(scan.next());</span><br><span class="line">}</span><br><span class="line">>><span class="number">123</span> <span class="number">456</span> <span class="number">789</span></span><br><span class="line">>><span class="number">123</span></span><br><span class="line">>><span class="number">456</span> </span><br><span class="line">>><span class="number">789</span></span><br><span class="line"><span class="type">Scanner</span> <span class="variable">scan</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Scanner</span>(System.in);</span><br><span class="line"><span class="keyword">while</span>(<span class="literal">true</span>){</span><br><span class="line"> System.out.println(scan.nextline());</span><br><span class="line">}</span><br><span class="line">>><span class="number">123</span> <span class="number">456</span> <span class="number">789</span></span><br><span class="line">>><span class="number">123</span> <span class="number">456</span> <span class="number">789</span></span><br><span class="line"><span class="comment">//同理有nextInt、nextDouble</span></span><br><span class="line"><span class="comment">//格式化输出值</span></span><br><span class="line"><span class="comment">//NumberFormat类</span></span><br><span class="line"><span class="type">double</span> <span class="variable">myNumber</span> <span class="operator">=</span> <span class="number">12345.123456789</span>;</span><br><span class="line"><span class="comment">//默认格式</span></span><br><span class="line"><span class="type">String</span> <span class="variable">myString</span> <span class="operator">=</span> NumberFormat.getInstance().format(myNumber);</span><br><span class="line"><span class="comment">//货币格式</span></span><br><span class="line"><span class="type">String</span> <span class="variable">myString</span> <span class="operator">=</span> NumberFormat.getCurrencyInstance().format(myNumber);</span><br><span class="line"><span class="comment">//通用数值格式</span></span><br><span class="line"><span class="type">String</span> <span class="variable">myString</span> <span class="operator">=</span> NumberFormat.getNumberInstance().format(myNumber);</span><br><span class="line"><span class="comment">//百分比格式</span></span><br><span class="line"><span class="type">String</span> <span class="variable">myString</span> <span class="operator">=</span> NumberFormat.getPercentInstance().format(myNumber);</span><br><span class="line"><span class="comment">/*...................................................................*/</span></span><br><span class="line"><span class="type">NumberFormat</span> <span class="variable">format</span> <span class="operator">=</span> NumberFormat.getInstance();</span><br><span class="line"><span class="comment">//设置格式 小数点后最少3位,最多5位</span></span><br><span class="line">format.setMinimumFractionDigits(<span class="number">3</span>);</span><br><span class="line">format.setMaximumFractionDigits(<span class="number">5</span>);</span><br><span class="line"><span class="comment">//整数部分最小位数</span></span><br><span class="line">format.setMinimumIntegerDigits(<span class="number">0</span>);</span><br><span class="line"><span class="comment">//DecimalFormat类</span></span><br><span class="line"><span class="comment">//bmi = 19.591836734693878</span></span><br><span class="line"><span class="comment">//小数点后三位</span></span><br><span class="line"><span class="type">DecimalFormat</span> <span class="variable">fmt</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DecimalFormat</span>(<span class="string">"0.###"</span>);</span><br><span class="line">System.out.println(fmt.format(bmi));</span><br><span class="line"><span class="comment">//小数点后两位</span></span><br><span class="line">fmt = <span class="keyword">new</span> <span class="title class_">DecimalFormat</span>(<span class="string">"0.##"</span>);</span><br><span class="line">System.out.println(fmt.format(bmi));</span><br></pre></td></tr></table></figure><h2 id="处理异常">处理异常</h2><p>错误可分为致命和非致命</p><p><strong>非致命</strong>:异常(Exception),修正后可以继续运行</p><p>ex:打开一个不存在的文件、除零溢出、数组越界</p><p><strong>致命</strong>:错误(Error),不能恢复</p><p>ex:内存耗尽</p><ul><li><p><strong>异常及处理机制(Exception类)</strong></p></li><li><p><strong>异常分类</strong></p></li></ul><figure><imgsrc="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpeterboazxu.com.cn%2Fblog%2F20201020%2FYaHreJb8buHd.png%3Fimageslim&refer=http%3A%2F%2Fpeterboazxu.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1669684929&t=f38e1148702b9a6c3816220e38efda03"alt="点击查看图片来源" /><figcaption aria-hidden="true">点击查看图片来源</figcaption></figure><figure><imgsrc="../images/java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20221030102220229.png"alt="image-20221030102220229" /><figcaption aria-hidden="true">image-20221030102220229</figcaption></figure><ul><li><strong>异常处理的方法</strong></li></ul><p><strong>在方法内处理</strong></p><p><strong>告诉方法的调用者来处理</strong></p><p>try块</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span>{</span><br><span class="line"> <span class="comment">//可能抛出一个IOException异常</span></span><br><span class="line">}<span class="keyword">catch</span>(IOException e){</span><br><span class="line"> <span class="comment">//处理代码</span></span><br><span class="line"> System.out.println(e.getMessage());</span><br><span class="line"> System.exit(<span class="number">0</span>);</span><br><span class="line">}</span><br><span class="line"><span class="comment">//一个catch块处理一个异常</span></span><br><span class="line">}<span class="keyword">catch</span>(IOException e){</span><br><span class="line"> <span class="comment">//处理代码</span></span><br><span class="line">}<span class="keyword">finally</span>{</span><br><span class="line"><span class="comment">//必须要执行的代码,除非之前调用了System.exit()</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li><strong>常见的异常</strong></li></ul><p>ArithmeticException 整数除法中,除数为0</p><p>NullPointerException 对象没有实例化</p><p>NegativeArraySizeException 数组坐标为负数</p><p>ArrayIndexOutOfBoundsException 访问数组下标越界</p><h1 id="第四章-面向对象程序设计重点">第四章面向对象程序设计(重点)</h1><h2 id="类和对象">类和对象</h2><ul><li>类的定义:包含数据成员变量和成员方法</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">修饰符 class 类名 [extends 父类名]{</span><br><span class="line"> 修饰符 类型 成员变量<span class="number">1</span>;</span><br><span class="line"> 修饰符 类型 成员变量<span class="number">2</span>;</span><br><span class="line"> ...</span><br><span class="line"> 修饰符 类型成员方法<span class="number">1</span>(参数列表){</span><br><span class="line"> 方法体</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure><imgsrc="../images/java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20221030102235260.png"alt="image-20221030102235260" /><figcaption aria-hidden="true">image-20221030102235260</figcaption></figure><ul><li>构造方法概述</li></ul><p>构造方法是特殊的方法,名字和类名相同,没有返回值(没有返回值类型,不能写void),在创建对象实例时通过new运算符自动调用。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloWorld</span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">Xyz</span> <span class="variable">test</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Xyz</span>();</span><br><span class="line"> <span class="comment">//普通方法得主动调用</span></span><br><span class="line"> test.Xyz();</span><br><span class="line"> <span class="type">Xyz</span> <span class="variable">test3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Xyz</span>(<span class="number">3</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Xyz</span>{</span><br><span class="line"> <span class="type">int</span> x;</span><br><span class="line"> <span class="comment">//构造方法1</span></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Xyz</span><span class="params">()</span>{</span><br><span class="line"> x = <span class="number">0</span>;</span><br><span class="line"> System.out.println(<span class="string">"Xyz()1"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//普通方法</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">Xyz</span><span class="params">()</span>{</span><br><span class="line"> x = <span class="number">0</span>;</span><br><span class="line"> System.out.println(<span class="string">"Xyz()2"</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//构造方法2</span></span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Xyz</span><span class="params">(<span class="type">int</span> i)</span>{</span><br><span class="line"> x = <span class="number">1</span>;</span><br><span class="line"> System.out.println(<span class="string">"Xyz(i)"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>每一个类必须至少有一个构造方法,如果程序员没有定义,系统会自动为该类生成一个默认的构造方法。</p><p>默认构造方法的参数列表和方法体均为空。所生成对象的各属性值也为空。</p><p>如果实例化的一个构造方法在类中没有定义,则系统会自动定义一个新的构造方法。</p><p><strong>构造方法重载 </strong> this</p><p>this关键字指代本类中的其他<strong>构造方法</strong>。还可以指名要操作的<strong>对象</strong>自身</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//构造方法的中的应用</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Student</span>{</span><br><span class="line"> String name;</span><br><span class="line"> <span class="type">int</span> age;</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Student</span><span class="params">(String s,<span class="type">int</span> n)</span>{</span><br><span class="line"> name = s;</span><br><span class="line"> age = n;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Student</span><span class="params">(String s)</span>{</span><br><span class="line"> <span class="built_in">this</span>(s, <span class="number">20</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="title function_">Student</span><span class="params">()</span>{</span><br><span class="line"> <span class="built_in">this</span>(<span class="string">"Unknown"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="comment">//指名对象</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Date</span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="type">int</span> day,month,year;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">printData</span><span class="params">()</span>{</span><br><span class="line"> System.out.println(<span class="string">"The current date is(dd/mm/yy):"</span> + <span class="built_in">this</span>.day + <span class="built_in">this</span>.month + <span class="built_in">this</span>.year);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="comment">//但同一个类中没必要用</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Date</span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="type">int</span> day,month,year;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">printData</span><span class="params">()</span>{</span><br><span class="line"> System.out.println(<span class="string">"The current date is(dd/mm/yy):"</span> + day + month + year);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>对象的创建和初始化</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//初始化</span></span><br><span class="line">变量名 = <span class="keyword">new</span> 类名(参数列表);</span><br><span class="line">类名 变量名 = <span class="keyword">new</span> 类名(参数列表);</span><br><span class="line"><span class="comment">//使用对象中的数据和方法</span></span><br><span class="line"><span class="comment">//类引用</span></span><br><span class="line">对象引用.成员数据;</span><br><span class="line">对象引用.成员数据(参数列表);</span><br><span class="line"><span class="comment">//引用变量的赋值</span></span><br></pre></td></tr></table></figure><figure><imgsrc="../images/java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20221030184035185.png"alt="image-20221030184035185" /><figcaption aria-hidden="true">image-20221030184035185</figcaption></figure><h2 id="定义方法">定义方法</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//格式</span></span><br><span class="line">修饰符 返回类型 方法名 (参数列表)块</span><br><span class="line"><span class="comment">//注:如果返回值为空,则括号里面不能加void </span></span><br></pre></td></tr></table></figure><ul><li>按值传递</li></ul><p>实参:传给方法的值</p><p>形参:方法的参数列表中列的值,形参是基本数据类型时,形参的任何修改不会影响实参;形参是引用时,改变实参。</p><figure><imgsrc="../images/java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20221030184156384.png"alt="image-20221030184156384" /><figcaption aria-hidden="true">image-20221030184156384</figcaption></figure><ul><li>重载方法名</li></ul><p>重载(Overload):允许多个方法使用同一个方法名(例如:构造方法)</p><p>因此方法的参数列表必须不完全相同(返回值不同,参数列表相同是不允许的)</p><h2 id="静态成员">静态成员</h2><p>静态变量:<strong>在类中用static修饰的成员(类似于全局变量)</strong></p><ul><li>静态与非静态成员的区别:非静态成员在实例化对象时分配内存,静态成员在类定义时还没创建对象。</li><li>静态成员可被不同对象共享,用作多个对象之间的通信。</li><li>静态类型也称为引用类型</li></ul><figure><imgsrc="../images/java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20221030184311286.png"alt="image-20221030184311286" /><figcaption aria-hidden="true">image-20221030184311286</figcaption></figure><p> 静态方法(类方法):</p><ul><li>静态方法不可以使用this,不能被重写</li></ul><figure><imgsrc="../images/java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20221030184433574.png"alt="image-20221030184433574" /><figcaption aria-hidden="true">image-20221030184433574</figcaption></figure><h2id="包装类在只能接受对象不能接受基本类型时使用可以方便类型之间的转换">包装类(在只能接受对象,不能接受基本类型时使用。可以方便类型之间的转换)</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">Integer</span> <span class="variable">ageObj</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Integer</span>(<span class="number">40</span>);</span><br></pre></td></tr></table></figure><figure><imgsrc="../images/java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20221030184532659.png"alt="image-20221030184532659" /><figcaption aria-hidden="true">image-20221030184532659</figcaption></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HW2</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">3</span>;</span><br><span class="line"> <span class="type">Integer</span> <span class="variable">integer</span> <span class="operator">=</span> i;</span><br><span class="line"> System.out.println(<span class="string">"integer:"</span>+integer.intValue());</span><br><span class="line"></span><br><span class="line"> <span class="comment">//类型转换</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">s</span> <span class="operator">=</span> <span class="string">"12"</span>;</span><br><span class="line"> i = Integer.parseInt(s);</span><br><span class="line"> System.out.println(<span class="string">"i="</span>+i);</span><br><span class="line"> System.out.println(<span class="string">"s="</span>+Integer.toString(i));</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>包装类中常常含有常量:MAX_VALUE,MIN_VALUE</p><p>自动装箱(基本数据类型->包装类):</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Integer obj1;</span><br><span class="line"><span class="type">int</span> <span class="variable">num1</span> <span class="operator">=</span> <span class="number">69</span>;</span><br><span class="line">obj1 = num1;</span><br></pre></td></tr></table></figure><h1 id="第五章-数组和字符串重点">第五章 数组和字符串(重点)</h1><h2 id="数组">数组</h2><ul><li>数组的声明</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//数组中元素数据类型相同 是一个对象 下标从0开始</span></span><br><span class="line"><span class="type">char</span> s[];</span><br><span class="line"><span class="type">int</span> intArray[];</span><br><span class="line">Date dateArrary[];</span><br><span class="line"><span class="comment">//或者</span></span><br><span class="line"><span class="type">char</span>[] s;</span><br><span class="line"><span class="comment">//注:不要在[]中写元素个数</span></span><br></pre></td></tr></table></figure><p>数组的声明仅仅分配了引用空间,没有分配内存空间</p><ul><li>创建数组(初始化)</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//静态初始化</span></span><br><span class="line"><span class="type">int</span> intArray[] = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>};</span><br><span class="line">String names[] = {<span class="string">"Jen"</span>,<span class="string">"Tom"</span>};</span><br><span class="line"><span class="comment">//动态初始化</span></span><br><span class="line">String names[];</span><br><span class="line">names = <span class="keyword">new</span> <span class="title class_">String</span>[<span class="number">4</span>];</span><br><span class="line">names[<span class="number">0</span>] = <span class="string">"Jane"</span>;</span><br><span class="line"><span class="comment">//基本数据类型创建</span></span><br><span class="line">类型 数组名[] = <span class="keyword">new</span> 类型[数组大小];</span><br><span class="line">类型 []数组名 = <span class="keyword">new</span> 类型[数组大小];</span><br><span class="line"><span class="type">char</span>[] s = <span class="keyword">new</span> <span class="title class_">char</span>[<span class="number">20</span>];</span><br><span class="line"><span class="comment">//类类型</span></span><br><span class="line">类型 []数组名 = <span class="keyword">new</span> 类型[数组大小];</span><br><span class="line">数组名[<span class="number">0</span>] = <span class="keyword">new</span> 类型(初值表);</span><br><span class="line">ex:</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Point</span>{...}</span><br><span class="line">Point points[];</span><br><span class="line">points = <span class="keyword">new</span> <span class="title class_">point</span>[<span class="number">100</span>];</span><br><span class="line">Point[<span class="number">0</span>] = <span class="keyword">new</span> <span class="title class_">Point</span>();</span><br><span class="line"></span><br><span class="line">Object[] points;</span><br><span class="line">points = <span class="keyword">new</span> <span class="title class_">point</span>[<span class="number">100</span>];<span class="comment">//允许</span></span><br><span class="line"></span><br><span class="line">Point [] points;</span><br><span class="line">points = <span class="keyword">new</span> <span class="title class_">Object</span>[<span class="number">100</span>];<span class="comment">//不允许</span></span><br></pre></td></tr></table></figure><ul><li>访问数组元素(和C语言里差不多)</li><li>初始化多维数组</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//初始化</span></span><br><span class="line"><span class="comment">//静态初始化</span></span><br><span class="line"><span class="type">int</span> intArray[] = {{<span class="number">2</span>,<span class="number">3</span>},{<span class="number">1</span>,<span class="number">5</span>},{<span class="number">3</span>,<span class="number">4</span>}};</span><br><span class="line"><span class="comment">//动态初始化</span></span><br><span class="line"><span class="comment">//直接分配</span></span><br><span class="line">类型 数组名[][] = <span class="keyword">new</span> 类型[第一维大小][第二维大小];</span><br><span class="line"><span class="comment">//按维分配</span></span><br><span class="line">类型 数组名[][] = <span class="keyword">new</span> 类型[第一维大小][];<span class="comment">//但只能从高维开始</span></span><br><span class="line">数组名[<span class="number">0</span>] = <span class="keyword">new</span> 类型[第二维大小];</span><br><span class="line">...<span class="comment">//每一行都要分配</span></span><br></pre></td></tr></table></figure><ul><li>多维数组引用</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//复制数组 bArr发生改变,aArr第二之后长度为3的元素复制到bArr元素2之后</span></span><br><span class="line">System.arraycopy(aArr,<span class="number">2</span>,bArr,<span class="number">2</span>,<span class="number">3</span>);</span><br></pre></td></tr></table></figure><h2 id="字符串类型">字符串类型</h2><p>Java的标准包java.lang中封装了String类(处理不变字符串)和StringBuffer类(可变)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//声明</span></span><br><span class="line">String s1;</span><br><span class="line">StringBuffer sb1;</span><br><span class="line"><span class="comment">//创建空字符串</span></span><br><span class="line"><span class="type">String</span> <span class="variable">s1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>();</span><br><span class="line"><span class="type">StringBuffer</span> <span class="variable">sb1</span> <span class="operator">=</span> StringBuffer();<span class="comment">//StringBuffer不能用字符串常量创建</span></span><br><span class="line"><span class="type">char</span> chars[] = {<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>};</span><br><span class="line"><span class="type">String</span> <span class="variable">s2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">String</span>(chars);</span><br></pre></td></tr></table></figure><ul><li>字符串操作</li></ul><p>String对象不可改变</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">length();</span><br><span class="line">charAt(<span class="type">int</span> index);</span><br><span class="line">subString(<span class="type">int</span> beginIndex);</span><br></pre></td></tr></table></figure><h2 id="vector类变长数组">Vector类(变长数组)</h2><p>数组类元素可不同</p><h1 id="第六章-继承和多态重点">第六章 继承和多态(重点)</h1><p>Java中类层次结构为树型结构,继承这一面向对象的特征,可支持软件的可复用行,可靠性,可维护性。例如:员工、经理有一些相同的属性(一般与特殊)。</p><h2 id="子类">子类</h2><ul><li>Java允许程序用以前已定义的类来定义一个新类,新类称为子类,原来的类称为父类/基类/超类。两类中共同的内容被放到父类中,特殊的内容放到子类中。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//用关键字extends表示派生</span></span><br><span class="line">修饰类 class 子类名 extends 父类名{</span><br><span class="line"> 类体</span><br><span class="line">}</span><br><span class="line"><span class="comment">//ex:</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">A</span> <span class="keyword">extends</span> <span class="title class_">B</span>{</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>若一个类的定义中没出现extends关键字,表明它派生于Object类(是所有类的父类或祖先)</p><ul><li>Object类</li></ul><p>Object类里面的方法</p><p>同一:两对象是否是同一对象</p><p>相等:两对象是否具有相同的类型和属性。同一必相等</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> Class <span class="title function_">getClass</span><span class="params">()</span>;<span class="comment">//获取当前对象所属类</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li>单重继承</li></ul><p>Java不能多重继承(多个类共同派生一个子类)。</p><p><strong>接口</strong>:一个特殊的类,实现多重继承的功能。</p><p>一个类可以继承所有祖先的属性和方法,但不能继承构造方法。也不能(直接)访问其父类中定义的私有(private)属性及方法。</p><ul><li>对象转型</li></ul><p>可以将子类的对象赋给父类的变量,反过来是错的</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">Employee</span> <span class="variable">e</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Manager</span>();</span><br><span class="line"><span class="comment">//判断一个引用指向哪个实例</span></span><br><span class="line">e <span class="keyword">instanceof</span> Manager</span><br><span class="line"><span class="comment">//若果e是Manager类 就可以进行类型转换</span></span><br><span class="line"><span class="type">Manager</span> <span class="variable">m</span> <span class="operator">=</span> (Manager)e;</span><br></pre></td></tr></table></figure><p>引用转型的规则:</p><p>(1)向上转型总合法(大转小)</p><p>(2)向下转型,只能由祖先转后代</p><h2 id="方法覆盖与多态">方法覆盖与多态</h2><ul><li>方法覆盖/方法重写/隐藏:修改父类中已有的方法。新方法的名字、返回类型、参数列表和父类完全一样。修改后子类和父类使用相同方法可以使用不同功能。</li></ul><p><strong>注</strong>:子类方法不能比父类访问权限更严格</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">A</span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">print</span><span class="params">()</span>{</span><br><span class="line"> System.out.println(<span class="string">"this is class A"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">B</span> <span class="keyword">extends</span> <span class="title class_">A</span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">print</span><span class="params">()</span>{</span><br><span class="line"> System.out.println(<span class="string">"this is class B"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloWorld</span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String [] args)</span>{</span><br><span class="line"><span class="type">B</span> <span class="variable">b</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">b</span>;</span><br><span class="line"> b.print();<span class="comment">//this is class B</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>方法的重载:一个类中的方法名字相同,参数列表不同。</p><p>重载与覆盖的区别:重载的方法属于同一个类,覆盖的方法分属于父类、子类。</p><p><strong>注</strong>:如果子类重写了父类的方法,但仍然想使用父类的方法,可以使用super关键字</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">super</span>.showPosition();<span class="comment">//使用父类中的showPosition方法</span></span><br></pre></td></tr></table></figure><p><strong>注</strong>:覆盖方法的允许访问范围不能小于原方法、抛出的异常不能比原方法多。</p><ul><li>调用父类的构造方法</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">super</span>(s);</span><br></pre></td></tr></table></figure><ul><li>多态:允许同一条方法调用指令在不同的上下文做不同的事情</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//例:如果Manager是Employee的子类,</span></span><br><span class="line"><span class="type">Manager</span> <span class="variable">m</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Manager</span>;</span><br><span class="line"><span class="type">Employee</span> <span class="variable">e</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">e</span>;</span><br><span class="line"><span class="comment">//e.getDetail()与m.getDetail()将执行不同的代码</span></span><br><span class="line"><span class="type">Employee</span> <span class="variable">e</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Manager</span>;</span><br><span class="line">e.getDetail();<span class="comment">//此时会调用Manager的</span></span><br></pre></td></tr></table></figure><h2 id="终极类与抽象类">终极类与抽象类</h2><p>终极:关键字final,可以修饰类、成员变量、成员方法。用final修饰的关键字和成员都是不能改变的(类不能有子类、方法不能被覆盖、变量的值不能被改变)。</p><p>抽象:关键字abstract,可作用于方法、类。用abstract修饰的方法的方法体为空,修饰的类必须被子类继承。</p><ul><li>终极类:不能被继承的类</li></ul><p>终极方法</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">final</span> 返回值类型 终极方法名([参数列表]){</span><br><span class="line">方法体</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>终极变量/终态变量就是一个常量。如果用final修饰一个引用变量,则这变量不能指向其他对象,但它所指对象中的属性可以改变。</p><ul><li>抽象类</li></ul><p>一些无法具体实现的类,只有方法名和头。</p><p>抽象方法必然包含在抽象类中。</p><p>抽象类不可以被实例化。但可以定义一个引用。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//抽象类的定义格式</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> class 抽象类名{</span><br><span class="line"> 类体</span><br><span class="line">}</span><br><span class="line"><span class="comment">//抽象方法</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> 返回值类型 抽象方法名([参数列表]){</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="接口">接口</h2><p>接口:体现抽象类功能,一个“纯的抽象类”。接口里的方法全是抽象方法。</p><p>Java允许一个类实现多个接口,从而实现多重继承的功能。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//接口的定义</span></span><br><span class="line">[接口修饰符] interface 接口名 [extends 父接口列表]{</span><br><span class="line">......<span class="comment">//方法原型或静态常量</span></span><br><span class="line">}</span><br><span class="line"><span class="comment">//接口与一般类一样,本身也具有数据成员变量与方法</span></span><br><span class="line"><span class="comment">//数据成员:隐式(public abstract)使用,必须是public static final,变量要赋初值,值不能再改</span></span><br><span class="line"><span class="comment">//例:</span></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">CharStorage</span>{</span><br><span class="line"><span class="keyword">void</span> <span class="title function_">put</span><span class="params">(<span class="type">char</span> c)</span>;<span class="comment">//抽象方法</span></span><br><span class="line"><span class="type">char</span> <span class="title function_">get</span><span class="params">()</span>;<span class="comment">//抽象方法</span></span><br><span class="line">}</span><br><span class="line"><span class="comment">//接口的实现</span></span><br><span class="line">class 类名 implements 接口名[.接口名[.接口名]]{</span><br><span class="line">...</span><br><span class="line">}</span><br><span class="line"><span class="comment">//例:</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Stack</span> <span class="keyword">implements</span> <span class="title class_">CharStorage</span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="type">char</span> mem[] = <span class="keyword">new</span> <span class="title class_">char</span>[ <span class="number">10</span>];</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>注:</p><p>在接口的定义中允许省略final、public等关键字</p><p>不能直接由接口创建对象</p><h1 id="第七章-输入和输出流">第七章 输入和输出流</h1><h2 id="数据流的基本概念">数据流的基本概念</h2><p>流:不同类型输入输出源的抽象</p><p>数据流:输入输出的数据,顺序的有起点、终点的字节集合</p><p>java.io包中提供表示数据流的4个基本抽象类:InputStream、OutputStream、Reader、Writer,需要importjava.io.*</p><ul><li>输入数据流(只读不能写)</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//主要操作方法</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">read</span><span class="params">()</span>;<span class="comment">//从输入流中读取二进制数</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">read</span><span class="params">(<span class="type">byte</span>[]b)</span>;<span class="comment">//多个字节读到数组</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">read</span><span class="params">(<span class="type">byte</span>[]b,<span class="type">int</span> of,<span class="type">int</span> len)</span>;<span class="comment">//读取长度为len的数据,从数组中坐标为of的位置开始读,返回字节数</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">close</span><span class="params">()</span>;<span class="comment">//关闭数据流</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">available</span><span class="params">()</span>;<span class="comment">//返回目前可读字节数</span></span><br><span class="line"><span class="type">long</span> <span class="title function_">skip</span><span class="params">(<span class="type">long</span> <span class="number">1</span>)</span>;<span class="comment">//跳过某些字节</span></span><br><span class="line"><span class="type">boolean</span> <span class="title function_">markSupported</span><span class="params">()</span>;<span class="comment">//查看是否支持回推操作</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">mark</span><span class="params">(<span class="type">int</span> markerea)</span>;<span class="comment">//标记数据流位置</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">reset</span><span class="params">()</span>;<span class="comment">//将输入流重新定位到对此流最后调用mark方法时的位置</span></span><br></pre></td></tr></table></figure><ul><li>输出数据流(只写不能读)</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> <span class="title function_">write</span><span class="params">(<span class="type">int</span> i)</span>;<span class="comment">//将字节i写入到数据流中,只输8位</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">write</span><span class="params">(<span class="type">byte</span> b[])</span>;<span class="comment">//将b数组中数据写入</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">write</span><span class="params">(<span class="type">byte</span> b[],<span class="type">int</span> off,<span class="type">int</span> len)</span>;</span><br><span class="line"><span class="keyword">void</span> <span class="title function_">close</span><span class="params">()</span>;</span><br><span class="line"><span class="keyword">void</span> <span class="title function_">flush</span><span class="params">()</span>;</span><br></pre></td></tr></table></figure><h2 id="基本字节数据流类">基本字节数据流类</h2><h2 id="基本字符流">基本字符流</h2><h2 id="文件的处理">文件的处理</h2><h1 id="第八章-图形界面设计重点">第八章 图形界面设计(重点)</h1><h2 id="awt与swing">AWT与Swing</h2><ul><li>GUI(图形用户界面):Java的GUI由各种组件组成,在java.awt包(标签Label、按钮Button)和javax.swing包(以J开头)中定义了多种组件类。</li></ul><p>设计GUI的步骤:选取组件、设计布局、响应事件。</p><ul><li>AWT、Swing(可以同时用,重量级的总是显示在上面)</li></ul><p><strong>AWT</strong></p><p>包含本地代码、重量级、平台的不同界面略有差异</p><p><strong>Swing</strong></p><p>在实现时不包含任何本地代码、轻量级、显示效果一致。功能更多按钮不光显示文本,还显示图标。</p><p><strong>组件</strong>:JButton、JTextField(文本框)、JLabel</p><p><strong>容器</strong>:Frame、Panel。特殊组件,可以包含组件,通过add()添加</p><h2 id="容器">容器</h2><p>容器分为:顶层容器、一般用途容器。非容器组件必须包含在容器中。</p><p>顶层容器:嵌套容器的最外层。</p><p>一般用途容器:不能在最外层,JPanel、JScrollPane。</p><ul><li>顶层容器</li></ul><p>Swing中有四种顶层容器:JFrame、JApplet、JDialog 、JWindow</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">JFrame<span class="comment">//带有标题行和控制按钮的独立窗口(框架)</span></span><br><span class="line"><span class="comment">//构造方法</span></span><br><span class="line">JFrame();<span class="comment">//创建一个初始不可见的、无标题的新框架窗口</span></span><br><span class="line">JFrame(String title);<span class="comment">//创建一个初始不可见的、有标题的新框架窗口</span></span><br><span class="line"><span class="comment">//其他方法</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">setBounds</span><span class="params">(<span class="type">int</span> x,<span class="type">int</span> y,<span class="type">int</span> width,<span class="type">int</span> height)</span>;<span class="comment">//调整框架大小</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">setSize</span><span class="params">(<span class="type">int</span> width,<span class="type">int</span> height)</span>;</span><br><span class="line"><span class="keyword">void</span> <span class="title function_">setBackground</span><span class="params">(Color bg)</span>;</span><br><span class="line"><span class="keyword">void</span> <span class="title function_">setVisible</span><span class="params">(<span class="type">boolean</span> aFlag)</span>;</span><br><span class="line"><span class="keyword">void</span> <span class="title function_">pack</span><span class="params">()</span>;<span class="comment">//调整适应框架的大小,以适合组件的首选大小</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">setTitle</span><span class="params">(String title)</span>;</span><br><span class="line">Container <span class="title function_">getContentPane</span><span class="params">()</span>;<span class="comment">//返回此窗口内容窗格子</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">setLayout</span><span class="params">(LayoutManager manager)</span>;<span class="comment">//设置布局管理器</span></span><br><span class="line"><span class="comment">//例子:</span></span><br><span class="line"><span class="keyword">import</span> java.awt.*;</span><br><span class="line"><span class="keyword">import</span> javax.swing.*;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloWorld</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="type">JFrame</span> <span class="variable">frame</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JFrame</span>(<span class="string">"JFrameDemo"</span>);</span><br><span class="line"> <span class="type">JButton</span> <span class="variable">button</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JButton</span>(<span class="string">"Press me"</span>);</span><br><span class="line"> <span class="comment">//加入按钮组件</span></span><br><span class="line"> frame.getContentPane().add(button,BorderLayout.CENTER);</span><br><span class="line"> frame.pack();</span><br><span class="line"> <span class="comment">//设置为可见</span></span><br><span class="line"> frame.setVisible(<span class="literal">true</span>);</span><br><span class="line"> <span class="comment">//关闭窗口</span></span><br><span class="line"> frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>内容窗格</li></ul><p>除了菜单外,顶层容器中的组件都放在内容窗格中。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//将顶层容器放在内容窗口的方法</span></span><br><span class="line"><span class="comment">//第一种方法:获得默认内容窗格</span></span><br><span class="line"><span class="comment">//返回类型:java.awt.Container</span></span><br><span class="line"><span class="type">Container</span> <span class="variable">contentPane</span> <span class="operator">=</span> frame.getContentPane();</span><br><span class="line">contentPane.add(button,BorderLayout.CENTER);</span><br><span class="line"><span class="comment">//第二种方法:创建新的内容窗格</span></span><br><span class="line"><span class="type">JPanel</span> <span class="variable">contentPane</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JPanel</span>;<span class="comment">//创建 实例</span></span><br><span class="line">contentPane.setLayout(<span class="keyword">new</span> <span class="title class_">BorderLayout</span>());<span class="comment">//创建布局管理器</span></span><br><span class="line"><span class="comment">//因为顶层容器的默认布局是BorderLayout,但JPanel的默认布局是FlowLayout</span></span><br><span class="line">contentPane.add(button,BorderLayout.CENTER);</span><br><span class="line">frame.setcontentPane(contentPane);</span><br><span class="line"><span class="comment">//例子:</span></span><br><span class="line"><span class="keyword">import</span> java.awt.*;</span><br><span class="line"><span class="keyword">import</span> javax.swing.*;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JFrameDemo2</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">JFrame</span> <span class="variable">frame</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JFrame</span>(<span class="string">"JFrameDemo2"</span>);</span><br><span class="line"> <span class="type">JButton</span> <span class="variable">button</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JButton</span>(<span class="string">"Press me"</span>);</span><br><span class="line"> <span class="type">JPanel</span> <span class="variable">panel</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JPanel</span>();</span><br><span class="line"> </span><br><span class="line"> panel.setLayout(<span class="keyword">new</span> <span class="title class_">BorderLayout</span>());</span><br><span class="line"> panel.add(button,BorderLayout.CENTER);</span><br><span class="line"> frame.setContentPane(panel);</span><br><span class="line"> frame.pack();</span><br><span class="line"> frame.setVisible(<span class="literal">true</span>);</span><br><span class="line"> frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>面板</li></ul><p>面板分为普通面板(JPanel)和滚动面板(JScrollPane)。</p><p>注:面板不能独立存在,必须要添加到其他容器内部,面板允许嵌套。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//JPanel常用构造方法</span></span><br><span class="line">JPanel();<span class="comment">//创建默认布局是FlowLayout的面板</span></span><br><span class="line">JPanel(LayoutManager layout);<span class="comment">//创建指定布局的面板</span></span><br><span class="line"><span class="keyword">public</span> Compononent <span class="title function_">add</span><span class="params">(Component comp)</span>;<span class="comment">//将组件加载到面板中</span></span><br><span class="line"><span class="comment">//JScrollPane(带有滚动条的面板)常用构造方法</span></span><br><span class="line"><span class="comment">//先将多个组件添加到JPanel,再将JPanel添加到JScrollPane</span></span><br><span class="line">JScrollPane();<span class="comment">//创建一个空的JScrollPane</span></span><br><span class="line">JScrollPane(Component view);<span class="comment">//显示制定组件</span></span><br><span class="line"><span class="comment">//常用方法</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">setHorizontalJScrollBarPolicy</span><span class="params">(<span class="type">int</span> policy)</span>;<span class="comment">//水平滚动条的显示</span></span><br><span class="line">Scrollbar();<span class="comment">//构建新的垂直滚动条</span></span><br><span class="line">Scrollbar(<span class="type">int</span> orientation);<span class="comment">//构建新的指定方向滚动条</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">JApplet</span><br><span class="line"><span class="comment">//创建小应用程序时使用 </span></span><br><span class="line">JDialog</span><br><span class="line"><span class="comment">//创建对话框</span></span><br><span class="line">JWindow </span><br><span class="line"><span class="comment">//不带标题行和控制按钮的独立窗口</span></span><br></pre></td></tr></table></figure><h2 id="标签和按钮">标签和按钮</h2><ul><li>标签(不可编辑)</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//构造方法</span></span><br><span class="line">JLabel();<span class="comment">//建立一个空标签</span></span><br><span class="line">JLabel(Icon image);<span class="comment">//建立一个显示图标的标签</span></span><br><span class="line">JLabel(String text);<span class="comment">//建立一个显示文本信息的标签</span></span><br><span class="line">JLabel(Icon image,<span class="type">int</span> horizontalAlignment);<span class="comment">//图标+对齐方式</span></span><br><span class="line">JLabel(String text,Icon image,<span class="type">int</span> horizontalAlignment);</span><br><span class="line"><span class="comment">//设置显示内容</span></span><br><span class="line">label.setHorizontalAlignment(JLabel.CENTRE);</span><br><span class="line">label.setVerticalAlignment(JLabel.BOTTOM);</span><br><span class="line">setText(String text);</span><br><span class="line">setIcon(Icon icon);</span><br></pre></td></tr></table></figure><ul><li>按钮</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line">JBotton、JToggleBotton、JCheckBox、JRadioButton</span><br><span class="line"><span class="comment">//一些常用方法,设置文本,设置图标,注册事件侦听程序</span></span><br><span class="line">addActionlistener();</span><br><span class="line">setEnabled();</span><br><span class="line">setText();</span><br><span class="line">setIcon;</span><br><span class="line"><span class="comment">//JBotton的一些构造方法</span></span><br><span class="line">JBotton();<span class="comment">//设置一个空按钮</span></span><br><span class="line">JBotton(Icon icon);</span><br><span class="line">JBotton(String text);</span><br><span class="line">JBotton(String text,Icon icon);</span><br><span class="line"><span class="comment">//鼠标单击时,事件处理系统向按钮发来一个ActionEvent事件类对象</span></span><br><span class="line">addActionlistener();<span class="comment">//为按钮注册时间侦听程序</span></span><br><span class="line"><span class="comment">//一些常用方法</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> setMemonic;<span class="comment">//设置当前按钮助记符 比如文件(F)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setText</span><span class="params">()</span>;<span class="comment">//设置按钮文本</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">getText</span><span class="params">()</span>;<span class="comment">//返回按钮文本</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setToolTipText</span><span class="params">(String text)</span>;<span class="comment">//设置提示文本</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> addActionListener;<span class="comment">//注册事件侦听程序</span></span><br><span class="line"><span class="comment">//例子:</span></span><br><span class="line"><span class="keyword">import</span> java.awt.*;</span><br><span class="line"><span class="keyword">import</span> java.awt.event.*;</span><br><span class="line"><span class="keyword">import</span> javax.swing.*;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JFrameDemo4</span> <span class="keyword">extends</span> <span class="title class_">WindowAdapter</span> <span class="keyword">implements</span> <span class="title class_">ActionListener</span>{</span><br><span class="line"> </span><br><span class="line"> JFrame f;</span><br><span class="line"> JButton b;</span><br><span class="line"> JTextField tf;</span><br><span class="line"> <span class="type">int</span> <span class="variable">tag</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="keyword">new</span> <span class="title class_">JFrameDemo4</span>();</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">go</span><span class="params">()</span>{</span><br><span class="line"> f = <span class="keyword">new</span> <span class="title class_">JFrame</span>(<span class="string">"JFrameDemo4"</span>);</span><br><span class="line"> b = <span class="keyword">new</span> <span class="title class_">JButton</span>(<span class="string">"press me"</span>);</span><br><span class="line"> b.addActionListener(<span class="built_in">this</span>);</span><br><span class="line"> f.getContentPane().add(b, <span class="string">"South"</span>);</span><br><span class="line"> tf = <span class="keyword">new</span> <span class="title class_">JTextField</span>();</span><br><span class="line"> f.getContentPane().add(tf,<span class="string">"Center"</span>);</span><br><span class="line"> f.addWindowListener(<span class="built_in">this</span>);</span><br><span class="line"></span><br><span class="line"> f.setVisible(<span class="literal">true</span>);</span><br><span class="line"> f.setSize(<span class="number">300</span>,<span class="number">150</span>);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span><span class="comment">//代表此方法是重写的</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">actionPerformed</span><span class="params">(ActionEvent e)</span> {</span><br><span class="line"> <span class="type">String</span> <span class="variable">s1</span> <span class="operator">=</span> <span class="string">"you have pressed the button!"</span>;</span><br><span class="line"> <span class="type">String</span> <span class="variable">s2</span> <span class="operator">=</span> <span class="string">"you pressed twice!"</span>;</span><br><span class="line"> <span class="keyword">if</span>(tag == <span class="number">0</span>){</span><br><span class="line"> tf.setText(s1);</span><br><span class="line"> tag = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span>{</span><br><span class="line"> tf.setText(s2);</span><br><span class="line"> tag = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>切换按钮、复选按钮、单选按钮</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//JToggleBotton(切换按钮)</span></span><br><span class="line"><span class="comment">//构造方法</span></span><br><span class="line">JToggleBotton();</span><br><span class="line">JToggleBotton(Icon icon);</span><br><span class="line">JToggleBotton(Icon icon,<span class="type">boolean</span> selected);<span class="comment">//有图标和初始状态</span></span><br><span class="line">JToggleBotton(String text);</span><br><span class="line">...</span><br><span class="line"><span class="comment">//boolean selected默认未选中</span></span><br><span class="line"><span class="comment">//一些其他方法</span></span><br><span class="line">selected();<span class="comment">//可以获得按钮当前状态</span></span><br><span class="line">isSelected();<span class="comment">//获取当前按钮有没有被选中</span></span><br><span class="line"><span class="comment">//JCheckBox(复选按钮)、JRadioButton(单选按钮)都是JToggleBotton(切换按钮)的子类</span></span><br><span class="line"><span class="comment">//JCheckBox(复选按钮)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//JRadioButton(单选按钮)</span></span><br></pre></td></tr></table></figure><h2 id="布局管理器">布局管理器</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//常用的布局管理器</span></span><br><span class="line"><span class="comment">//FlowLayout、BorderLayout、GridLayout、CardLayout、BoxLayout、空布局</span></span><br><span class="line"><span class="comment">//FlowLayout布局方式:将组件逐个放在容器的一行上</span></span><br><span class="line">FlowLayout();</span><br><span class="line">FlowLayout(<span class="type">int</span> align);</span><br><span class="line">FlowLayout(<span class="type">int</span> align,<span class="type">int</span> hgap,<span class="type">int</span> vgap);</span><br><span class="line"><span class="comment">//例:</span></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">FlowLayout</span>(FlowLayout.LEFT,<span class="number">20</span>,<span class="number">40</span>);</span><br><span class="line">setLayout(<span class="keyword">new</span> <span class="title class_">FlowLayout</span>());</span><br><span class="line"><span class="comment">//例:</span></span><br><span class="line"><span class="keyword">import</span> java.awt.*;</span><br><span class="line"><span class="keyword">import</span> javax.swing.*;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JFrameDemo5</span> {</span><br><span class="line"> <span class="keyword">private</span> JFrame frame;</span><br><span class="line"> <span class="keyword">private</span> JButton button1,button2,button3;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">JFrameDemo5</span> <span class="variable">be</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JFrameDemo5</span>();</span><br><span class="line"> be.go();</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">go</span><span class="params">()</span>{</span><br><span class="line"> frame = <span class="keyword">new</span> <span class="title class_">JFrame</span>(<span class="string">"JFrameDemo5"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="type">Container</span> <span class="variable">contentPane</span> <span class="operator">=</span> frame.getContentPane();</span><br><span class="line"> contentPane.setLayout(<span class="keyword">new</span> <span class="title class_">FlowLayout</span>());</span><br><span class="line"></span><br><span class="line"> button1 = <span class="keyword">new</span> <span class="title class_">JButton</span>(<span class="string">"ok"</span>);</span><br><span class="line"> button2 = <span class="keyword">new</span> <span class="title class_">JButton</span>(<span class="string">"open"</span>);</span><br><span class="line"> button3 = <span class="keyword">new</span> <span class="title class_">JButton</span>(<span class="string">"close"</span>);</span><br><span class="line"> contentPane.add(button1);</span><br><span class="line"> contentPane.add(button2);</span><br><span class="line"> contentPane.add(button3);</span><br><span class="line"></span><br><span class="line"> frame.setSize(<span class="number">200</span>, <span class="number">100</span>);</span><br><span class="line"> frame.setVisible(<span class="literal">true</span>);</span><br><span class="line"> frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//BorderLayout</span></span><br><span class="line"><span class="comment">//BorderLayout.NORTh;BorderLayout.SOUTH;BorderLayout.WEST;BorderLayout.EAST,每个区域只能放一个组件,若放多个组件,最后一个有效</span></span><br><span class="line">BorderLayout();<span class="comment">//构造一个布局管理器</span></span><br><span class="line">BorderLayout(<span class="type">int</span> hgap,<span class="type">int</span> vgap);</span><br><span class="line"><span class="comment">//在BorderLayout布局管理器下,组件必须通过add()方法加入容器。</span></span><br><span class="line"><span class="comment">//例子:</span></span><br><span class="line">frame.getContentPane().add(button,BorderLayout.SOUTH);</span><br><span class="line"><span class="comment">//或者</span></span><br><span class="line">frame.getContentPane().add(button,<span class="string">"South"</span>);</span><br><span class="line"><span class="comment">//例:</span></span><br><span class="line"><span class="keyword">import</span> javax.swing.*;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JFrameDemo6</span> {</span><br><span class="line"> JFrame frame;</span><br><span class="line"> JButton be,bn,bw,bs,bc;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">JFrameDemo6</span> <span class="variable">be</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JFrameDemo6</span>();</span><br><span class="line"> be.go();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">go</span><span class="params">()</span>{</span><br><span class="line"> frame = <span class="keyword">new</span> <span class="title class_">JFrame</span>(<span class="string">"BorderLayot"</span>);</span><br><span class="line"> be = <span class="keyword">new</span> <span class="title class_">JButton</span>(<span class="string">"east"</span>);</span><br><span class="line"> bn = <span class="keyword">new</span> <span class="title class_">JButton</span>(<span class="string">"north"</span>);</span><br><span class="line"> bw = <span class="keyword">new</span> <span class="title class_">JButton</span>(<span class="string">"west"</span>);</span><br><span class="line"> bs = <span class="keyword">new</span> <span class="title class_">JButton</span>(<span class="string">"south"</span>);</span><br><span class="line"> bc = <span class="keyword">new</span> <span class="title class_">JButton</span>(<span class="string">"center"</span>);</span><br><span class="line"></span><br><span class="line"> frame.getContentPane().add(bc,<span class="string">"Center"</span>);</span><br><span class="line"> frame.getContentPane().add(be, <span class="string">"East"</span>);</span><br><span class="line"> frame.getContentPane().add(bn, <span class="string">"North"</span>);</span><br><span class="line"> frame.getContentPane().add(bs, <span class="string">"South"</span>);</span><br><span class="line"> frame.getContentPane().add(bw, <span class="string">"West"</span>);</span><br><span class="line"></span><br><span class="line"> frame.setSize(<span class="number">350</span>,<span class="number">200</span>);</span><br><span class="line"> frame.setVisible(<span class="literal">true</span>);</span><br><span class="line"> frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//GridLayout 网格状布局管理器</span></span><br><span class="line">GridLayout();<span class="comment">//创建只有一行的网格</span></span><br><span class="line">GridLayout(<span class="type">int</span> rows,<span class="type">int</span> cols);<span class="comment">//两参数不能全是0</span></span><br><span class="line">GridLayout(<span class="type">int</span> rows,<span class="type">int</span> cols,<span class="type">int</span> hgap,<span class="type">int</span> vgap);</span><br><span class="line"><span class="comment">//每列宽度相同,每行高度相同,组件放入次序决定位置</span></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//CardLayout布局管理器</span></span><br><span class="line"><span class="comment">//卡片式布局管理器,每次只显示一张</span></span><br><span class="line">CardLayout();</span><br><span class="line">CardLayout(<span class="type">int</span> hgap,<span class="type">int</span> vgap);</span><br><span class="line"><span class="comment">//常用方法</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">first</span><span class="params">(Container parent)</span><span class="comment">//翻转到第一张卡片</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">last</span><span class="params">(Container parent)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">previous</span><span class="params">(Container parent)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">next</span><span class="params">(Container parent)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">show</span><span class="params">(Container parent,String name)</span></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//BoxLayout</span></span><br><span class="line"><span class="comment">//一行或一列,高度宽度不同</span></span><br><span class="line">BoxLayout(Container target,<span class="type">int</span> axis);<span class="comment">//target为哪个容器设置布局管理器,axis排列方向 Y_AXIS;X_AXIS</span></span><br><span class="line"><span class="comment">//Box类 本身是容器</span></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//空布局</span></span><br><span class="line">contentPane.setLayout(<span class="literal">null</span>);</span><br></pre></td></tr></table></figure><h2 id="事件处理">事件处理</h2><p>用户事件:用户在程序界面所进行的操作</p><p>事件处理:对事件的响应</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//鼠标事件MouseEvent 键盘事件KeyEvent</span></span><br><span class="line"><span class="comment">//事件类对象ActionEvent</span></span><br><span class="line"><span class="comment">//对应ActionEvent事件有ActionListener接口</span></span><br><span class="line"><span class="comment">//当出现ActionEvent事件时,就会调用该方法</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">ActionListener</span> <span class="keyword">extends</span> <span class="title class_">EventListener</span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">actionPerformed</span><span class="params">(ActionEvent e)</span>;</span><br><span class="line">}</span><br><span class="line"><span class="comment">//注册事件监听程序</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addActionListener</span><span class="params">(ActionListener I)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">removeActionListener</span><span class="params">(ActionListener I)</span></span><br></pre></td></tr></table></figure><ul><li>事件处理模型</li></ul><p>动作产生事件,事件被送往事件注册程序</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//事件的种类</span></span><br><span class="line"><span class="comment">//ActionEvent ItemEvent MouseEvent KeyEvent</span></span><br></pre></td></tr></table></figure><ul><li>事件适配器</li></ul><p>为同一时间注册多个事件处理程序</p><h2 id="绘图基础">绘图基础</h2><ul><li>Graphics2D绘图</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//stroke属性</span></span><br><span class="line"><span class="comment">//控制线的宽度、笔形样式、线段连接方式</span></span><br><span class="line">BasicStroke(<span class="type">float</span> w);<span class="comment">//指定宽度</span></span><br><span class="line">BasicStroke(<span class="type">float</span> w,<span class="type">int</span> cap,<span class="type">int</span> join);<span class="comment">//指定宽度、端点样式、连接方式</span></span><br><span class="line"><span class="comment">//paint属性</span></span><br><span class="line"><span class="comment">//控制填充效果</span></span><br><span class="line">GradientPaint(<span class="type">float</span> x1,<span class="type">float</span> y2,Color c1,<span class="type">float</span> x2,<span class="type">float</span> y2,Color c2);</span><br><span class="line"><span class="comment">//(x1,y1)到(x2,y2) 从c1渐变到c2</span></span><br><span class="line">GradientPaint(<span class="type">float</span> x1,<span class="type">float</span> y2,Color c1,<span class="type">float</span> x2,<span class="type">float</span> y2,Color c2,Boolean cyclic);<span class="comment">//颜色的变化是周期的</span></span><br><span class="line"><span class="comment">//transform属性</span></span><br><span class="line"><span class="comment">//对图像进行变形:平移、缩放、斜切</span></span><br><span class="line">AffineTransform();<span class="comment">//构造一个仿射</span></span><br><span class="line">getRotateInstance(<span class="type">double</span> theta);<span class="comment">//选择theta弧度</span></span><br><span class="line">getRotateInstance(<span class="type">double</span> theta,<span class="type">double</span> x,<span class="type">double</span> y);<span class="comment">//绕旋转中心(x,y)旋转</span></span><br><span class="line">getScaleInstance(<span class="type">double</span> sx,<span class="type">double</span> sy);<span class="comment">//x、y方向按比例缩放</span></span><br><span class="line">getTranslateInstance(<span class="type">double</span> tx,<span class="type">double</span> ty);<span class="comment">//平移变换</span></span><br><span class="line">getShearInstance(<span class="type">double</span> shx,<span class="type">double</span> shy);<span class="comment">//斜切变换</span></span><br><span class="line"><span class="comment">//clip属性</span></span><br><span class="line"><span class="comment">//裁剪</span></span><br><span class="line">setClip();</span><br><span class="line"><span class="comment">//composit属性</span></span><br><span class="line"><span class="comment">//处理重叠区域</span></span><br><span class="line">AlphaComposite.getInstance(<span class="type">int</span> rule,<span class="type">float</span> alpha);</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//例子:</span></span><br><span class="line"><span class="keyword">import</span> java.awt.*;</span><br><span class="line"><span class="keyword">import</span> javax.swing.*;</span><br><span class="line"><span class="keyword">import</span> java.awt.geom.*; </span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GraphicDemo</span> {</span><br><span class="line"> JFrame frame;</span><br><span class="line"> JPanel panel;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">GraphicDemo</span> <span class="variable">de</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">GraphicDemo</span>();</span><br><span class="line"> de.go();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">go</span><span class="params">()</span>{</span><br><span class="line"> frame = <span class="keyword">new</span> <span class="title class_">JFrame</span>(<span class="string">"Drawing Ex"</span>);</span><br><span class="line"> panel = <span class="keyword">new</span> <span class="title class_">MyPanel</span>();</span><br><span class="line"></span><br><span class="line"> frame.getContentPane().add(panel, <span class="string">"Center"</span>);</span><br><span class="line"> frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);</span><br><span class="line"> frame.setSize(<span class="number">360</span>,<span class="number">200</span>);</span><br><span class="line"> frame.setVisible(<span class="literal">true</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">class</span> <span class="title class_">MyPanel</span> <span class="keyword">extends</span> <span class="title class_">JPanel</span>{</span><br><span class="line"> <span class="keyword">protected</span> <span class="keyword">void</span> <span class="title function_">paintComponent</span><span class="params">(Graphics g)</span>{</span><br><span class="line"> <span class="built_in">super</span>.paintComponent(g);</span><br><span class="line"> <span class="comment">//画圆弧</span></span><br><span class="line"> <span class="type">Graphics2D</span> <span class="variable">g2d</span> <span class="operator">=</span> (Graphics2D)g;</span><br><span class="line"> <span class="type">Shape</span> <span class="variable">arc</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Arc2D</span>.Float(<span class="number">30</span>,<span class="number">30</span>,<span class="number">150</span>,<span class="number">150</span>,<span class="number">40</span>,<span class="number">100</span>,Arc2D.OPEN);</span><br><span class="line"> g2d.draw(arc);</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//一些图形类</span></span><br><span class="line"><span class="comment">//线段</span></span><br><span class="line"><span class="type">Line2D</span> <span class="variable">line</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Line2D</span>.Double(<span class="number">2</span>,<span class="number">3</span>,<span class="number">200</span>,<span class="number">300</span>);</span><br><span class="line"><span class="comment">//矩形 左上角坐标+宽+高</span></span><br><span class="line"><span class="type">Rectangle2D</span> <span class="variable">rect</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Rectangle2D</span>.Double(<span class="number">20</span>,<span class="number">30</span>,<span class="number">80</span>,<span class="number">40</span>);</span><br><span class="line"><span class="comment">//圆角矩形</span></span><br><span class="line"><span class="type">RoundRectangle2D</span> <span class="variable">rectRound</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">RoundRectangle2D</span>.Double(<span class="number">20</span>,<span class="number">30</span>,<span class="number">130</span>,<span class="number">100</span>,<span class="number">18</span>,<span class="number">15</span>);</span><br><span class="line"><span class="comment">//椭圆 一个矩形区域确定一个椭圆</span></span><br><span class="line"><span class="type">Elipse2D</span> <span class="variable">elipse</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Elipse2D</span>.Double(<span class="number">20</span>,<span class="number">30</span>,<span class="number">100</span>,<span class="number">50</span>);</span><br><span class="line"><span class="comment">//圆弧 外接矩形左上角+宽+高+起始角+终止角+开弧(不封闭)</span></span><br><span class="line"><span class="type">Arc2D</span> <span class="variable">arcl</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Arc2D</span>.Double(<span class="number">8</span>,<span class="number">30</span>,<span class="number">85</span>,<span class="number">60</span>,<span class="number">5</span>,<span class="number">270</span>,Arc2D.OPEN);</span><br><span class="line">Arc2D.CHORD<span class="comment">//弓弧</span></span><br><span class="line">Arc2D.PIE<span class="comment">//饼弧</span></span><br><span class="line"><span class="comment">//二次曲线 始点+控制点+终点</span></span><br><span class="line">curve1 = <span class="keyword">new</span> <span class="title class_">QuadCurve2D</span>.Double(<span class="number">20</span>,<span class="number">10</span>,<span class="number">90</span>,<span class="number">65</span>,<span class="number">55</span>,<span class="number">115</span>);</span><br><span class="line"><span class="comment">//三次曲线 CubicCurve2D</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="第九章-swing组件重点">第九章 Swing组件(重点)</h1><h2 id="组合框与列表">组合框与列表</h2><ul><li>组合框(JComboBox):下拉式菜单(不可编辑/可编辑)</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//构造方法</span></span><br><span class="line">JComboBox();</span><br><span class="line">JComboBox(Object[] items);<span class="comment">//Object[]中元素为可选项</span></span><br><span class="line">setEditable(<span class="literal">true</span>);<span class="comment">//设为可编辑</span></span><br><span class="line"><span class="comment">//其他方法</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">addItem</span><span class="params">(Object anObject)</span>;<span class="comment">//在末尾添加新的可选项</span></span><br><span class="line">Object <span class="title function_">getItemAt</span><span class="params">(<span class="type">int</span> index)</span>;<span class="comment">//某个位置的item</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">getItemCount</span><span class="params">()</span>;<span class="comment">//项数</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">insertItemAt</span><span class="params">(Object anObject,<span class="type">int</span> index)</span>;</span><br><span class="line"><span class="comment">//用户事件</span></span><br><span class="line"><span class="comment">//输入项目后 Enter Actionlistener</span></span><br><span class="line"><span class="comment">//选定项目 ItemListener</span></span><br></pre></td></tr></table></figure><ul><li>列表(JList)可选项</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//构造方法</span></span><br><span class="line">JList();</span><br><span class="line">JList(Object[] listData);</span><br><span class="line">JList(Vector<?> listData);</span><br><span class="line"><span class="comment">//用户事件 ListSelectionEvent</span></span><br><span class="line">addListSelectionListener(ListSelectionListener listener);</span><br><span class="line">Public <span class="keyword">void</span> <span class="title function_">valueChanged</span><span class="params">(ListSelectionEvent e)</span></span><br></pre></td></tr></table></figure><h2 id="文本组件">文本组件</h2><p>文本域(JTextField)、口令输入域(JPasswordField)、文本区(JTextArea)</p><p>文本组件的父类:JTextComponent</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//JTextComponent</span></span><br><span class="line">String <span class="title function_">getSelectedText</span><span class="params">()</span>;<span class="comment">//提取被选中的文本内容</span></span><br><span class="line">String <span class="title function_">getText</span><span class="params">()</span>;<span class="comment">//提取所有文本内容</span></span><br><span class="line"><span class="comment">//JComponent</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">requestFocusInWindow</span><span class="params">()</span>;</span><br></pre></td></tr></table></figure><ul><li>JTextField</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//单行文本输入框</span></span><br><span class="line"><span class="comment">//构造方法</span></span><br><span class="line">JTextField();</span><br><span class="line">JTextField(<span class="type">int</span> columns);</span><br><span class="line">JTextField(String text);</span><br><span class="line"><span class="comment">//常用</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">addActionListener</span><span class="params">(ActionListener I)</span>;</span><br><span class="line"><span class="keyword">void</span> <span class="title function_">removeActionListener</span><span class="params">(ActionListener I)</span>;</span><br><span class="line"><span class="keyword">void</span> <span class="title function_">setFont</span><span class="params">(Font f)</span>;</span><br><span class="line"><span class="type">int</span> <span class="title function_">getColumns</span><span class="params">()</span>;</span><br></pre></td></tr></table></figure><ul><li>JTextArea</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//多行多列</span></span><br><span class="line"><span class="comment">//构造方法</span></span><br><span class="line">JTextArea();</span><br><span class="line">JTextArea(String text);</span><br><span class="line">JTextArea(<span class="type">int</span> rows,<span class="type">int</span> columns);</span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">append</span><span class="params">(String str)</span>;</span><br><span class="line"><span class="keyword">void</span> <span class="title function_">insert</span><span class="params">(String str,<span class="type">int</span> pos)</span>;</span><br><span class="line"><span class="keyword">void</span> <span class="title function_">replaceRange</span><span class="params">(String str,<span class="type">int</span> start,<span class="type">int</span> end)</span>;</span><br></pre></td></tr></table></figure><h2 id="菜单组件">菜单组件</h2><ul><li>下拉式菜单</li></ul><p>菜单栏包含菜单项</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//菜单栏构造方法</span></span><br><span class="line">JMenuBar();</span><br><span class="line"><span class="type">JMenuBar</span> <span class="variable">mb</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JMenuBar</span>();</span><br><span class="line">frame.setJMenuBar(mb);</span><br><span class="line"><span class="comment">//菜单的构造方法</span></span><br><span class="line">JMenu();</span><br><span class="line">JMenu(String s,<span class="type">boolean</span> b);<span class="comment">//b菜单是否可以分离</span></span><br><span class="line">mb.add(menu1);<span class="comment">//菜单加入菜单栏</span></span><br><span class="line"><span class="comment">//菜单项</span></span><br><span class="line">JMenuItem();</span><br><span class="line">JMenuItem(Icon icon);</span><br><span class="line">JMenuItem(String text);</span><br><span class="line"><span class="comment">//设置快捷键、加速键</span></span><br><span class="line"><span class="comment">//快捷键、加速键的区别:快捷键只有在出现该菜单时才可以使用,加速键例如Alt+1</span></span><br><span class="line">setAccelerator(KeyStroke keyStroke);</span><br><span class="line"><span class="comment">//在菜单项之间加入分隔线</span></span><br><span class="line">menu1.addSeparator();</span><br><span class="line">menu1.add(<span class="keyword">new</span> <span class="title class_">Separator</span>());</span><br><span class="line"><span class="comment">//嵌套菜单</span></span><br><span class="line"><span class="comment">//用户事件</span></span><br><span class="line">menuitem.addActionListener(<span class="built_in">this</span>);<span class="comment">//注册侦听器</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//例1:</span></span><br><span class="line"><span class="keyword">import</span> java.awt.*;</span><br><span class="line"><span class="keyword">import</span> java.awt.event.*;</span><br><span class="line"><span class="keyword">import</span> javax.swing.*;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MenuDemo</span> {</span><br><span class="line"> JFrame frame;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">MenuDemo</span> <span class="variable">be</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">MenuDemo</span>();</span><br><span class="line"> be.go();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">go</span><span class="params">()</span>{</span><br><span class="line"> frame = <span class="keyword">new</span> <span class="title class_">JFrame</span>(<span class="string">"MenuDemo"</span>);</span><br><span class="line"> <span class="comment">//菜单栏</span></span><br><span class="line"> <span class="type">JMenuBar</span> <span class="variable">menuBar</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JMenuBar</span>();</span><br><span class="line"> <span class="comment">//菜单项</span></span><br><span class="line"> <span class="type">JMenu</span> <span class="variable">menu1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JMenu</span>(<span class="string">"File"</span>);</span><br><span class="line"> <span class="type">JMenu</span> <span class="variable">menu2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JMenu</span>(<span class="string">"Edit"</span>);</span><br><span class="line"> menuBar.add(menu1);</span><br><span class="line"> menuBar.add(menu2);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//菜单</span></span><br><span class="line"> <span class="type">JMenuItem</span> <span class="variable">mi1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JMenuItem</span>(<span class="string">"Save"</span>,KeyEvent.VK_S);<span class="comment">//设置快捷键</span></span><br><span class="line"> <span class="type">JMenuItem</span> <span class="variable">mi2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JMenuItem</span>(<span class="string">"Load"</span>);</span><br><span class="line"> <span class="type">JMenuItem</span> <span class="variable">mi3</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JMenuItem</span>(<span class="string">"Quit"</span>);</span><br><span class="line"> menu1.add(mi1);</span><br><span class="line"> menu1.add(mi2);</span><br><span class="line"> menu1.add(mi3);</span><br><span class="line"></span><br><span class="line"> frame.getContentPane().add(menuBar, <span class="string">"North"</span>);</span><br><span class="line"></span><br><span class="line"> frame.setSize(<span class="number">300</span>,<span class="number">200</span>);</span><br><span class="line"> frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);</span><br><span class="line"> frame.setVisible(<span class="literal">true</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>复选菜单项(方框)和单选菜单项(圆圈)</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//构造复选菜单项</span></span><br><span class="line">JCheckBoxMenuItem();</span><br><span class="line">JCheckBoxMenuItem(Icon icon);</span><br><span class="line">JCheckBoxMenuItem(String text);</span><br><span class="line"><span class="comment">//构造单选菜单项</span></span><br><span class="line">JRadioButtonMenuItem();</span><br><span class="line"><span class="comment">//用户事件ItemEvent</span></span><br><span class="line">itemStateChanged();</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2id="对话框临时的可移动窗口依赖于其他窗口">对话框:临时的可移动窗口,依赖于其他窗口</h2><ul><li>对话框分为强制性(不可中断)、非强制性</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//对话框构造方法</span></span><br><span class="line">JDialog(Dialog owner);</span><br><span class="line">JDialog(Dialog owner,<span class="type">boolean</span> modal);</span><br><span class="line">JDialog(Dialog owner,String title);</span><br><span class="line"><span class="comment">//例子</span></span><br><span class="line"><span class="type">JDialog</span> <span class="variable">dialog</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JDialog</span>(frame,<span class="string">"Dialog"</span>,<span class="literal">true</span>);</span><br><span class="line">setVisible(<span class="literal">true</span>);</span><br></pre></td></tr></table></figure><ul><li>标准对话框</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">showConfirmDialog;<span class="comment">//确认对话框</span></span><br><span class="line">showInputDialog;<span class="comment">//输入对话框</span></span><br><span class="line">showMessageDialog;<span class="comment">//信息对话框</span></span><br><span class="line">showOptionDialog;<span class="comment">//选项对话框</span></span><br></pre></td></tr></table></figure><ul><li>文件对话框(专门用于对文件(或目录进行浏览的对话框))</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//构造方法</span></span><br><span class="line">JFileChooser();</span><br><span class="line">JFileChooser(File currentDirectory);</span><br><span class="line">JFileChooser(String currentDirectoryPath);</span><br><span class="line">showOpenDialog(Component parent);<span class="comment">//弹出一个“打开”文件对话框</span></span><br><span class="line">showSaveDialog(Component parent);<span class="comment">//弹出一个“保存”文件对话框</span></span><br><span class="line">getSelectedFile();<span class="comment">//取得文件</span></span><br></pre></td></tr></table></figure><h1 id="第十章-多线程">第十章 多线程</h1><h2 id="线程和多线程">线程和多线程</h2><ul><li>概念</li></ul><p>程序:静态</p><p>进程:动态的概念,是程序的一次动态执行。</p><p>线程:嵌在进程里面,是进程执行过程中产生的多条执行线索</p><ul><li>线程的结构</li></ul><p>虚拟CPU+执行的代码+处理的数据</p><p>线程间可以直接共享数据和资源</p><p>应用:同时监听网络和输入</p><p>Thread类实现多线程</p><ul><li>线程的状态</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//新建(New)、可运行状态(Runnable)、死亡(Dead)、阻塞(Blocked)</span></span><br></pre></td></tr></table></figure><figure><imgsrc="../images/java%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image-20221103195027844.png"alt="image-20221103195027844" /><figcaption aria-hidden="true">image-20221103195027844</figcaption></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//1.新建</span></span><br><span class="line"><span class="comment">//线程对象刚刚创建,还没有启动,处于不可运行状态,但已有相应内存空间</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//2.可运行状态</span></span><br><span class="line"><span class="comment">//线程已启动,可能正在运行或不在运行。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//3.死亡状态</span></span><br><span class="line"><span class="comment">//死亡原因:run()方法执行完毕;线程遇到异常退出时</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//4.阻塞</span></span><br><span class="line"><span class="comment">//sleep()或者wait()</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//5.中断</span></span><br><span class="line"><span class="comment">//interrupt()会抛出一个InterruptedExeption异常</span></span><br><span class="line"><span class="comment">//测试是否被中断</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">interrupt</span><span class="params">()</span>;<span class="comment">//发生中断请求</span></span><br><span class="line"><span class="keyword">static</span> <span class="type">boolean</span> <span class="title function_">interrupted</span><span class="params">()</span>;</span><br><span class="line"><span class="type">boolean</span> <span class="title function_">idInterrupted</span><span class="params">()</span>;</span><br></pre></td></tr></table></figure><h2 id="创建线程">创建线程</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//创建线程的两种方法</span></span><br><span class="line"><span class="comment">//1.继承一个Thread类(java.lang.Thread)的子类</span></span><br><span class="line">Thread(ThreadGRoup group,Runnable target,String name);</span><br><span class="line"><span class="comment">//name 新线程名字 线程组group中一员</span></span><br><span class="line"><span class="comment">//target 实现run()方法</span></span><br><span class="line"><span class="comment">//2.实现Runnable接口</span></span><br><span class="line"><span class="comment">//定义一个线程类,继承Thread类并重写方法run()</span></span><br></pre></td></tr></table></figure><ul><li>继承Thread类创建线程</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//从Thread类派生一个子类,实现run()</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Lefthand</span> <span class="keyword">extends</span> <span class="title class_">Thread</span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span>{......}<span class="comment">//线程体,进行重写</span></span><br><span class="line">}</span><br><span class="line"><span class="comment">//用该类创建一个对象</span></span><br><span class="line"><span class="type">Lefthand</span> <span class="variable">left</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Lefthand</span>();</span><br><span class="line"><span class="comment">//用start()方法启动线程。</span></span><br><span class="line">left.start();</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//例子</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">LeftHand</span> <span class="keyword">extends</span> <span class="title class_">Thread</span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;i < <span class="number">5</span>;i++){</span><br><span class="line"> System.out.println(<span class="string">"I am LeftHand!"</span>);</span><br><span class="line"> <span class="keyword">try</span>{</span><br><span class="line"> sleep(<span class="number">500</span>);</span><br><span class="line"> }<span class="keyword">catch</span>(InterruptedException e){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">RightHand</span> <span class="keyword">extends</span> <span class="title class_">Thread</span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;i < <span class="number">5</span>;i++){</span><br><span class="line"> System.out.println(<span class="string">"I am RightHand!"</span>);</span><br><span class="line"> <span class="keyword">try</span>{</span><br><span class="line"> sleep(<span class="number">300</span>);</span><br><span class="line"> }<span class="keyword">catch</span>(InterruptedException e){</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ThreadDemo1</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="type">LeftHand</span> <span class="variable">lh</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">LeftHand</span>();</span><br><span class="line"> <span class="type">RightHand</span> <span class="variable">rh</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">RightHand</span>();</span><br><span class="line"> lh.start();</span><br><span class="line"> rh.start();<span class="comment">//注意:这里不是run();</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>Runnable接口创建线程(依然用start()启动)</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//例子</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ThreadDemo2</span> {</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> {</span><br><span class="line"> <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;i < <span class="number">10</span>;i++){</span><br><span class="line"> System.out.println(Thread.currentThread().getName() + <span class="string">"\t\t"</span> + i);</span><br><span class="line"> <span class="keyword">if</span>(i == <span class="number">5</span>){</span><br><span class="line"> <span class="type">TwoThread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">TwoThread</span>();</span><br><span class="line"> <span class="type">Thread</span> <span class="variable">thread1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(t1,<span class="string">"线程1"</span>);</span><br><span class="line"> <span class="type">Thread</span> <span class="variable">thread2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(t1,<span class="string">"线程2"</span>);</span><br><span class="line"> thread1.start();</span><br><span class="line"> thread2.start();</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">TwoThread</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="type">int</span> i;</span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> {</span><br><span class="line"> <span class="comment">// TODO Auto-generated method stub</span></span><br><span class="line"> <span class="keyword">for</span>(i = <span class="number">0</span>;i < <span class="number">20</span>;i++){</span><br><span class="line"> System.out.println(Thread.currentThread().getName() + <span class="string">"\t\t"</span> + i);</span><br><span class="line"> <span class="keyword">if</span>(i == <span class="number">20</span>){</span><br><span class="line"> System.out.println(Thread.currentThread().getName() + <span class="string">"\t\t"</span> + <span class="string">"over"</span>);</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>两种创建方法的适用条件</li></ul><h2 id="线程的基本控制">线程的基本控制</h2><ul><li>线程的启动</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Thread1.start();<span class="comment">//并不会立即启动,而是根据线程的调度</span></span><br><span class="line"><span class="comment">//有关线程的启动</span></span><br><span class="line">start();<span class="comment">//让线程从新建变就绪</span></span><br><span class="line">run();<span class="comment">//定义线程被调度后执行的操作,必须重写</span></span><br><span class="line"><span class="keyword">yield</span>();<span class="comment">//强制终止线程的执行</span></span><br><span class="line">isAlive();<span class="comment">//测试当前线程是否在活动</span></span><br><span class="line">sleep(<span class="type">int</span> millisecond);<span class="comment">//时间单位为ms</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">wait</span><span class="params">()</span>;<span class="comment">//使线程处于等待</span></span><br></pre></td></tr></table></figure><ul><li>线程的调度</li></ul><p>Java中的线程调度是抢占式,不是时间片的</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//按优先级进行调度</span></span><br><span class="line">MAX_PRIORITY 最高优先级 <span class="number">10</span></span><br><span class="line">MIN_PRIORITY 最低优先级 <span class="number">1</span></span><br><span class="line">NORM_PRIORITY 默认优先级 <span class="number">5</span></span><br><span class="line"><span class="comment">//常用方法</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">setPriority</span><span class="params">(<span class="type">int</span> newPriority)</span>;<span class="comment">//重置线程优先级</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">getPriority</span><span class="params">()</span>;<span class="comment">//获取当前线程优先级</span></span><br><span class="line"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">yield</span><span class="params">()</span>;<span class="comment">//暂停当前线程</span></span><br></pre></td></tr></table></figure><p>sleep()调用允许低优先级进程运行,而yield()方法只给同优先级进程以运行的机会。</p><ul><li>结束进程</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//自然死亡 run()结束</span></span><br><span class="line"><span class="comment">//强迫死亡</span></span><br></pre></td></tr></table></figure><ul><li>挂起线程</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//sleep();</span></span><br><span class="line"><span class="comment">//wait(); notify(); notifyAll();</span></span><br><span class="line"><span class="comment">//join();引起现行线程等待,直至join()方法所用的线程结束</span></span><br></pre></td></tr></table></figure><h2 id="线程的互斥">线程的互斥</h2><ul><li>对象互斥锁实现不同线程对共享数据操作的同步(两种方法实现)</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//第一种,volatile声明一个共享变量</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//第二种,synchronized声明一个方法或一段代码 临界区</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">push</span><span class="params">(<span class="type">char</span> c)</span>{</span><br><span class="line"><span class="keyword">synchronized</span>(){.....}</span><br><span class="line">}</span><br><span class="line"><span class="comment">//或者</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title function_">push</span><span class="params">(<span class="type">char</span> c)</span>{</span><br><span class="line"> ......</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="线程的同步">线程的同步</h2><ul><li>协调线程间的运行速度关系</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//wait(); notify(); notifyAll();在java.lang.Object中</span></span><br><span class="line">wait();<span class="comment">//释放对象互斥锁,进入等待队列</span></span><br><span class="line">notify();<span class="comment">//唤醒等待队列中线程,进入对象互斥锁</span></span><br><span class="line"><span class="comment">//这些方法只能在声明synchronized的代码段中使用</span></span><br><span class="line"><span class="comment">//等待</span></span><br><span class="line"><span class="keyword">if</span>(drainingBoard.isEmpty())</span><br><span class="line"> drainingBoard.wait();</span><br><span class="line"><span class="comment">//唤醒</span></span><br><span class="line">drainingBoard.addItem(plate);</span><br><span class="line">drainingBoard.notify();</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> 编程 </category>
<category> java </category>
</categories>
<tags>
<tag> java入门 </tag>
<tag> 编程 </tag>
</tags>
</entry>
</search>