-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
336 lines (336 loc) · 80.8 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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[Decryptable algorithm for java]]></title>
<url>%2F2019%2F04%2F03%2Fdecryptable-algorithm-for-java%2F</url>
<content type="text"><![CDATA[123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263public class CrypToUtils { private static final String UNICODE_FORMAT = "UTF8"; public static final String DESEDE_ENCRYPTION_SCHEME = "DESede"; private KeySpec ks; private SecretKeyFactory skf; private Cipher cipher; byte[] arrayBytes; private String myEncryptionKey; private String myEncryptionScheme; SecretKey key; public CrypToUtils() throws Exception { myEncryptionKey = "kOkzc^qxwJXiUvXvoaps$a3#"; myEncryptionScheme = DESEDE_ENCRYPTION_SCHEME; arrayBytes = myEncryptionKey.getBytes(UNICODE_FORMAT); ks = new DESedeKeySpec(arrayBytes); skf = SecretKeyFactory.getInstance(myEncryptionScheme); cipher = Cipher.getInstance(myEncryptionScheme); key = skf.generateSecret(ks); } public String fixKeyEncode(String unencryptedString) { String encryptedString = null; try { cipher.init(Cipher.ENCRYPT_MODE, key); byte[] plainText = unencryptedString.getBytes(UNICODE_FORMAT); byte[] encryptedText = cipher.doFinal(plainText); encryptedString = new String(Base64.encodeBase64(encryptedText)); } catch (Exception e) { e.printStackTrace(); } return encryptedString; } public String fixKeyDecode(String encryptedString) { String decryptedText=null; try { cipher.init(Cipher.DECRYPT_MODE, key); byte[] encryptedText = Base64.decodeBase64(encryptedString); byte[] plainText = cipher.doFinal(encryptedText); decryptedText= new String(plainText); } catch (Exception e) { e.printStackTrace(); } return decryptedText; } public static void main(String[] args) throws Exception { CrypToUtils td= new CrypToUtils(); String target="16"; String encrypted=td.fixKeyEncode(target); String decrypted=td.fixKeyDecode(encrypted); System.out.println("String To Encrypt: "+ target); System.out.println("Encrypted String:" + encrypted); System.out.println("Decrypted String:" + decrypted); }}]]></content>
</entry>
<entry>
<title><![CDATA[@Lock缓存设计的流程]]></title>
<url>%2F2019%2F04%2F02%2Flock-annotation-design%2F</url>
<content type="text"><![CDATA[流程图:]]></content>
</entry>
<entry>
<title><![CDATA[@Cache缓存设计的流程]]></title>
<url>%2F2019%2F04%2F02%2Fcache-annotation-design%2F</url>
<content type="text"><![CDATA[流程图如下:]]></content>
</entry>
<entry>
<title><![CDATA[How to use postman to bulk insert data in Elasticsearch]]></title>
<url>%2F2019%2F03%2F20%2FHow-to-use-postman-to-bulk-insert-data-in-Elasticsearch%2F</url>
<content type="text"><![CDATA[Request method: POST Headers: [“Content-Type”: “application/x-ndjson”] Body type: raw Body content format: Every json String must newline. And per-line json String must has no space. Body content example:1234{"index":{"_index":"schools_","_type":"school","_id":"1"}}{"name":"Model School","description":"CBSE Affiliation","street":"silk city","city":"Hyderabad","state":"AP","zip":"500030","location":[17.3903703,78.4752129],"fees":200,"tags":["Senior Secondary","beautiful campus"],"rating":"3"}{"index":{"_index":"schools_","_type":"school","_id":"2"}}{"name":"Government School","description":"State Board Affiliation","street":"Hinjewadi","city":"Pune","state":"MH","zip":"411057","location":[18.599752,73.6821995],"fees":500,"tags":["Great Sports"],"rating":"4"} This is an example, click to download and import to postman: Postman export example]]></content>
</entry>
<entry>
<title><![CDATA[Python3 + Centos7: No module named 'MySQLdb']]></title>
<url>%2F2019%2F03%2F19%2FNo-module-named-MySQLdb%2F</url>
<content type="text"><![CDATA[12sudo yum install mariadb-devel sudo pip3 install mysqlclient]]></content>
</entry>
<entry>
<title><![CDATA[Apriori Algorithm]]></title>
<url>%2F2018%2F07%2F08%2FApriori-Algorithm%2F</url>
<content type="text"><![CDATA[123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960"""Apriori exercise."""def load_dataset(): return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]'''输入:源数据功能:从源数据提取候选项返回:1item是大小为1的所有候选项集的集合'''def create_1item(dataset): k_items = [] for transaction in dataset: for item in transaction: if [item] not in k_items: k_items.append([item]) k_items.sort() return list(map(frozenset, k_items))'''输入: 总数据集 k项的所有组合 最小支持度功能:计算k_items中的项集在数据集中的支持度输出: 满足支持度的候选项 各个候选项支持度'''def scan_dataset(dataset, k_items, min_support): k_item_dict = {} for transaction in dataset: for k_item in k_items: # 对于每一个候选项集k_item,检查是否是transaction的一部分 if k_item.issubset(transaction): k_item_dict[k_item] = k_item_dict.get(k_item, 0) + 1 # 总记录数 dataset_count = float(len(dataset)) result_list = [] support_dict = {} for k_item in k_item_dict: # 每个项集的支持度 = 包含该项集的记录 / 总记录 support = k_item_dict[k_item] / dataset_count # 将满足最小支持度的项集,加入retList if support >= min_support: result_list.insert(0, k_item) # 汇总支持度数据 support_dict[k_item] = support return result_list, support_dictif __name__ == '__main__': k_items = create_1item(load_dataset()) result_tuple = scan_dataset(load_dataset(), k_items, 0.5) # print(type(result_tuple)) print(result_tuple[0]) print(result_tuple[1])]]></content>
</entry>
<entry>
<title><![CDATA[基于用户的协同过滤算法]]></title>
<url>%2F2018%2F07%2F04%2F%E5%9F%BA%E4%BA%8E%E7%94%A8%E6%88%B7%E7%9A%84%E5%8D%8F%E5%90%8C%E8%BF%87%E6%BB%A4%E7%AE%97%E6%B3%95%2F</url>
<content type="text"><![CDATA[电影点赞数据:https://grouplens.org/datasets/movielens/123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266# -*- coding=utf-8 -*-import mathimport sysfrom texttable import Texttable## 使用 |A&B|/sqrt(|A||B|)计算余弦距离###def calcCosDistSpe(user1, user2): avg_x = 0.0 avg_y = 0.0 for key in user1: avg_x += key[1] avg_x = avg_x / len(user1) for key in user2: avg_y += key[1] avg_y = avg_y / len(user2) u1_u2 = 0.0 for key1 in user1: for key2 in user2: if key1[1] > avg_x and key2[1] > avg_y and key1[0] == key2[0]: u1_u2 += 1 u1u2 = len(user1) * len(user2) * 1.0 sx_sy = u1_u2 / math.sqrt(u1u2) return sx_sy## 计算余弦距离##def calcCosDist(user1, user2): sum_x = 0.0 sum_y = 0.0 sum_xy = 0.0 for key1 in user1: for key2 in user2: if key1[0] == key2[0]: sum_xy += key1[1] * key2[1] sum_y += key2[1] * key2[1] sum_x += key1[1] * key1[1] if sum_xy == 0.0: return 0 sx_sy = math.sqrt(sum_x * sum_y) return sum_xy / sx_sy### 相似余弦距离###def calcSimlaryCosDist(user1, user2): sum_x = 0.0 sum_y = 0.0 sum_xy = 0.0 avg_x = 0.0 avg_y = 0.0 for key in user1: avg_x += key[1] avg_x = avg_x / len(user1) for key in user2: avg_y += key[1] avg_y = avg_y / len(user2) for key1 in user1: for key2 in user2: if key1[0] == key2[0]: sum_xy += (key1[1] - avg_x) * (key2[1] - avg_y) sum_y += (key2[1] - avg_y) * (key2[1] - avg_y) sum_x += (key1[1] - avg_x) * (key1[1] - avg_x) if sum_xy == 0.0: return 0 sx_sy = math.sqrt(sum_x * sum_y) return sum_xy / sx_sy## 读取文件##def readFile(file_name): contents_lines = [] f = open(file_name, "r") contents_lines = f.readlines() f.close() return contents_lines## 解压rating信息,格式:用户id,电影id,用户rating,时间# 输入:数据集合# 输出:已经解压的排名信息#def getRatingInformation(ratings): rates = [] for line in ratings[1:]: rate = line.split(",") rates.append([int(rate[0]), int(rate[1]), float(rate[2])]) return rates## 生成用户评分的数据结构## 输入:所以数据 [[2,1,5],[2,4,2]...]# 输出:1.用户打分字典 2.电影字典# 使用字典,key是用户id,value是用户对电影的评价,# rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2#def createUserRankDic(rates): user_rate_dic = {} item_to_user = {} for i in rates: user_rank = (i[1], i[2]) if i[0] in user_rate_dic: user_rate_dic[i[0]].append(user_rank) else: user_rate_dic[i[0]] = [user_rank] if i[1] in item_to_user: item_to_user[i[1]].append(i[0]) else: item_to_user[i[1]] = [i[0]] return user_rate_dic, item_to_user## 计算与指定用户最相近的邻居# 输入:# 指定用户ID# 所有用户数据。用户字典:dic[用户id]=[(电影id,电影评分)...]# 所有物品数据。电影字典:dic[电影id]=[用户id1,用户id2...]# 输出:与指定用户最相邻的邻居列表#def calcNearestNeighbor(userid, users_dic, item_dic): neighbors = [] # neighbors.append(userid) for item in users_dic[userid]: for neighbor in item_dic[item[0]]: if neighbor != userid and neighbor not in neighbors: # 共同喜欢item物品的用户 neighbors.append(neighbor) neighbors_dist = [] for neighbor in neighbors: # calcSimlaryCosDist calcCosDist calcCosDistSpe dist = calcSimlaryCosDist(users_dic[userid], users_dic[neighbor]) neighbors_dist.append([dist, neighbor]) neighbors_dist.sort(reverse=True) # print neighbors_dist return neighbors_dist## 使用UserFC进行推荐# 输入:文件名,用户ID,邻居数量# 输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表#def recommendByUserFC(file_name, userid, k=5): # 读取文件数据 test_contents = readFile(file_name) # 文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] test_rates = getRatingInformation(test_contents) # 格式化成字典数据 # 1.用户字典:dic[用户id]=[(电影id,电影评分)...] # 2.电影字典:dic[电影id]=[用户id1,用户id2...] test_user_dic, test_item_to_user = createUserRankDic(test_rates) # 邻近用户列表:[(和指定用户的距离,用户id)...] neighbors = calcNearestNeighbor(userid, test_user_dic, test_item_to_user)[:k] # 推荐列表:{"电影id":"累计推荐得分"...} recommend_dic = {} for neighbor in neighbors: neighbor_user_id = neighbor[1] movies = test_user_dic[neighbor_user_id] for movie in movies: if movie[0] not in recommend_dic: recommend_dic[movie[0]] = neighbor[0] else: # 累计推荐得分 recommend_dic[movie[0]] += neighbor[0] # 建立推荐列表:[(累计推荐得分,电影id)...] recommend_list = [] for key in recommend_dic: # print key recommend_list.append([recommend_dic[key], key]) # 按得分排序 recommend_list.sort(reverse=True) # 指定用户喜欢的电影列表 user_movies = [i[0] for i in test_user_dic[userid]] return [i[1] for i in recommend_list], user_movies, test_item_to_user, neighbors### 获取电影的列表,格式:电影id,电影名,电影发布时间###def getMoviesList(file_name): # print sys.getdefaultencoding() movies_contents = readFile(file_name) movies_info = {} for movie in movies_contents[1:]: movie_info = movie.split(",") movies_info[int(movie_info[0])] = movie_info[1:] return movies_info# 主程序# 输入 : 测试数据集合if __name__ == '__main__': # reload(sys) # sys.setdefaultencoding('utf-8') movies = getMoviesList("E:\\data_mining\\recommend\\ml-latest-small\\movies.csv") # 推荐电影列表:["电影id"...] # 指定用户喜欢的电影列表:["电影id"...] # 电影字典:dic[电影id]=[用户id1,用户id2...] # 邻近用户列表:[(和指定用户的距离,用户id)...] recommend_list, user_movie, items_movie, neighbors = recommendByUserFC("E:\\data_mining\\recommend\\ml-latest-small\\ratings.csv", 179, 80) # 所有邻近的用户列表:["用户id"...] neighbors_id = [i[1] for i in neighbors] table = Texttable() table.set_deco(Texttable.HEADER) # t: text # f: float (decimal) # e: float (exponent) # i: integer # a: automatic table.set_cols_dtype(['t', 't', 't']) # l: left # r: right # c: center table.set_cols_align(["l", "l", "l"]) rows = [] rows.append(["movie name", "release", "from userid"]) # 前20推荐电影id for movie_id in recommend_list[:20]: from_user = [] # 喜欢该电影的所有用户id for user_id in items_movie[movie_id]: # 并且为邻近用户 if user_id in neighbors_id: from_user.append(str(user_id)) # 取出电影的信息 rows.append([movies[movie_id][0], movies[movie_id][1], ','.join(from_user)]) table.add_rows(rows) print(table.draw())]]></content>
</entry>
<entry>
<title><![CDATA[Funny Website]]></title>
<url>%2F2018%2F07%2F04%2FFunny-Website%2F</url>
<content type="text"><![CDATA[Sentdex Blog: https://pythonprogramming.net/Sentdex Youtube: https://www.youtube.com/user/sentdex/featured?pbjreload=10 WSL(Windows Subsystem for Linux): https://chocolatey.org/]]></content>
</entry>
<entry>
<title><![CDATA[JaccardSimilarity计算文本相似度]]></title>
<url>%2F2018%2F07%2F03%2FJaccardSimilarity%E8%AE%A1%E7%AE%97%E6%96%87%E6%9C%AC%E7%9B%B8%E4%BC%BC%E5%BA%A6%2F</url>
<content type="text"><![CDATA[123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241# -*- coding=utf-8 -*-### refer to : https://github.com/wyh267/myCodeLib/blob/master/Src/textDiff/JaccardSimilarity.py## 利用jaccard similarity 计算文本相似度####import osimport timeimport progressbar############################################### 读取文件,保存到一个字符串中# 输入: 文件名完整路径# 输出: 文件内容##############################################def read_file(file_name): f = open(file_name, "r") file_contents = f.read() file_contents = file_contents.replace("\t", "") file_contents = file_contents.replace("\r", "") file_contents = file_contents.replace("\n", "") f.close() return file_contents############################################### 分割字符串,使用k-shingle方式进行分割# 输入:字符串,k值# 输出:分割好的字符串,存入数组中##############################################def split_contents(content, k=5): content_split = [] for i in range(len(content) - k): content_split.append(content[i:i + k]) return content_split############################################### 将数据保存到hash表中,也就是某个集合# 输入:已经分隔好的数据# 输出:hash表##############################################def hash_contents_list(content_list): hash_content = {} for i in content_list: if i in hash_content: hash_content[i] = hash_content[i] + 1 else: hash_content[i] = 1 return hash_content############################################### 计算交集# 输入:两个hash表# 输出:交集的整数##############################################def calc_intersection(hash_a, hash_b): intersection = 0 if (len(hash_a) <= len(hash_b)): hash_min = hash_a hash_max = hash_b else: hash_min = hash_b hash_max = hash_a for key in hash_min: if key in hash_max: if (hash_min[key] <= hash_max[key]): intersection = intersection + hash_min[key] else: intersection = intersection + hash_max[key] return intersection############################################### 计算并集# 输入:两个hash表# 输出:并集的整数##############################################def calc_union_set(hash_a, hash_b, intersection): union_set = 0 for key in hash_a: union_set = union_set + hash_a[key] for key in hash_b: union_set = union_set + hash_b[key] return union_set - intersection############################################### 计算相似度# 输入:交集和并集# 输出:相似度# #############################################def calc_similarity(intersection, union_set): if (union_set > 0): return float(intersection) / float(union_set) else: return 0.0############################################### 从某个文本文件获取一个集合,该集合保存了文本中单词的出现频率# 输入:文件名,k值,默认为5# 输出:一个词频的hash表##############################################def get_hash_info_from_file(file_name, k=5): content = read_file(file_name) content_list = split_contents(content, k) hash_content = hash_contents_list(content_list) return hash_content############################################### 获取文件列表# 输入:目录名# 输出:文件列表,文件名列表############################################## def collect_file_list(file_path): print("获取文件列表....") start = time.time() file_name_list = [] file_names = [] for parent, dirnames, filenames in os.walk(file_path): # print filenames for file_name in filenames: if (file_name[-4:] == ".txt"): file_name_list.append(file_path + file_name) file_names.append(file_name) end = time.time() print("获取文件列表结束,用时: " + str(end - start) + u"秒") return file_name_list, file_names############################################### 获取每个文件词汇# 输入:文件列表# 输出:词汇表列表############################################## def get_all_files_words_list(file_name_list, file_names, k=5): print("获取每个文本的词汇词频表....") start = time.time() hash_contents = [] all = float(len(file_name_list)) pos = 0.0 pro = progressbar.ProgressBar().start() # 获取每个文本的词汇词频表 for index, file_name in enumerate(file_name_list): pos = pos + 1 rate_num = int(pos / all * 100) pro.update(rate_num) # time.sleep(0.1) hash_contents.append([get_hash_info_from_file(file_name, k), file_names[index]]) pro.finish() end = time.time() print("获取每个文本的词汇词频表结束,用时: " + str(end - start) + u"秒") return hash_contents############################################### 计算两两相似度# 输入:哈希数据列表# 输出:相似度数组############################################## def calc_each_similar(hash_contents): print("计算所有文本互相之间的相似度....") start = time.time() similar_list = [] all = float(len(hash_contents)) pos = 0.0 pro = progressbar.ProgressBar().start() for index1, v1 in enumerate(hash_contents): pos = pos + 1 rate_num = int(pos / all * 100) pro.update(rate_num) # time.sleep(0.1) # print "%02d" % int(pos/all*100), for index2, v2 in enumerate(hash_contents): if (v1[1] != v2[1] and index2 > index1): intersection = calc_intersection(v1[0], v2[0]) # 计算交集 union_set = calc_union_set(v1[0], v2[0], intersection) # 计算并集 similar = calc_similarity(intersection, union_set) similar_list.append([similar, v1[1], v2[1]]) # print v1[1]+ "||||||" + v2[1] + " similarity is : " + str(calcSimilarity(intersection,union_set)) #计算相似度 pro.finish() similar_list.sort() similar_list.reverse() end = time.time() print("计算所有文本互相之间的相似度结束,用时: " + str(end - start) + u"秒") return similar_list############################################### 主程序# 输入:路径和k-shingle中的k值# 输出:两两相似度数组##############################################def calc_similarity_by_words(file_path, k=5): # 获取文件列表 file_name_list, file_names = collect_file_list(file_path) # 获取每个文件词汇 hash_contents = get_all_files_words_list(file_name_list, file_names, k) # 计算文件的相似度 res = calc_each_similar(hash_contents) return resprint(calc_similarity_by_words("G:\\temp\\"))]]></content>
</entry>
<entry>
<title><![CDATA[个人文档记录]]></title>
<url>%2F2018%2F05%2F24%2F%E4%B8%AA%E4%BA%BA%E6%96%87%E6%A1%A3%E8%AE%B0%E5%BD%95%2F</url>
<content type="text"><![CDATA[RAP返回信息模板1{"ret":"","msg":"","data":{}} Windows 10 hosts文件位置1C:\Windows\System32\Drivers\etc\hosts]]></content>
</entry>
<entry>
<title><![CDATA[CopyOnWriteArrayList的原理和方法]]></title>
<url>%2F2018%2F05%2F16%2FCopyOnWriteArrayList%E7%9A%84%E5%8E%9F%E7%90%86%E5%92%8C%E6%96%B9%E6%B3%95%2F</url>
<content type="text"><![CDATA[对比遍历有更新操作ArrayList普通数组123456789101112131415161718192021222324252627282930313233343536373839404142434445import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class CopyOnWriteArrayListTest { static List<Integer> list = new ArrayList(){{add(20);add(30);add(40);}}; static class Thread1 extends Thread { @Override public void run() { Iterator iterator = list.iterator(); System.out.print("1 : "); // 仅仅打印数组的第一个元素 if (iterator.hasNext()) { System.out.print(iterator.next() + " "); } System.out.println(); try { sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } // 打印数组剩下的元素 System.out.print("2 : "); while (iterator.hasNext()) { System.out.print(iterator.next() + " "); } System.out.println(); } } static class Thread2 extends Thread { @Override public void run() { list.add(50); System.out.println("2 : " + list); } } public static void main(String[] args) { new Thread1().start(); new Thread2().start(); }} 结果抛出异常信息:1234Exception in thread "Thread-0" 2 : java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) at java.util.ArrayList$Itr.next(ArrayList.java:851) at cn.com.xbed.csbapp.service.impl.CopyOnWriteArrayListTest$Thread1.run(CopyOnWriteArrayListTest.java:29) CopyOnWriteArrayList复制写入数组1234567891011121314151617181920212223242526272829303132333435363738394041424344454647import java.util.Iterator;import java.util.concurrent.CopyOnWriteArrayList;public class CopyOnWriteArrayListTest { static Integer[] os = new Integer[]{20, 30, 40}; static CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList(os); static class Thread1 extends Thread { @Override public void run() { Iterator iterator = list.iterator(); System.out.print("1 : "); // 仅仅打印数组的第一个元素 if (iterator.hasNext()) { System.out.print(iterator.next() + " "); } System.out.println(); try { sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } // 打印数组剩下的元素 // 还是初始拿到的数组,更新后的数组不会在这里 System.out.print("2 : "); while (iterator.hasNext()) { System.out.print(iterator.next() + " "); } System.out.println(); } } static class Thread2 extends Thread { @Override public void run() { // 复制新数组,再写入,不会影响已遍历的 list.add(50); System.out.println("2 : " + list); } } public static void main(String[] args) { new Thread1().start(); new Thread2().start(); }}]]></content>
<tags>
<tag>高并发</tag>
<tag>Java</tag>
</tags>
</entry>
<entry>
<title><![CDATA[各种排序算法比较]]></title>
<url>%2F2018%2F05%2F11%2F%E5%90%84%E7%A7%8D%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95%E6%AF%94%E8%BE%83%2F</url>
<content type="text"><![CDATA[各种排序算法比较]]></content>
<tags>
<tag>排序</tag>
</tags>
</entry>
<entry>
<title><![CDATA[C语言读写文件详解]]></title>
<url>%2F2018%2F05%2F11%2FC%E8%AF%AD%E8%A8%80%E8%AF%BB%E5%86%99%E6%96%87%E4%BB%B6%E8%AF%A6%E8%A7%A3%2F</url>
<content type="text"><![CDATA[123456789101112131415161718192021222324252627282930313233343536#include <stdio.h>int main(){ // 写入模式 FILE* writer = fopen("C:\\data.txt", "w"); if (writer == NULL) { return 0; } for (int i = 0; i < 10; i++) { fprintf(writer, "%d ", i); } fclose(writer); // 读入模式 FILE* reader = fopen("C:\\data.txt", "r"); if (reader == NULL) { return 0; } int nums[10] = {0}; for (int i = 0; i < 10; i++) { fscanf(reader, "%d ", &nums[i]); } // 打印保存的值 for (int i = 0; i < 10; i++) { printf("%d ", i); } fclose(reader); return 1;}]]></content>
<tags>
<tag>C语言</tag>
<tag>文件读写</tag>
</tags>
</entry>
<entry>
<title><![CDATA[C++文件读写详解]]></title>
<url>%2F2018%2F05%2F11%2Fcplusplus%E6%96%87%E4%BB%B6%E8%AF%BB%E5%86%99%E8%AF%A6%E8%A7%A3%2F</url>
<content type="text"><![CDATA[12345678910111213141516171819202122232425262728#include <iostream>// 文件流包#include <fstream>// 读取一行需要存在字符串中#include <string>// ifstream是在名称空间std下的,必须引入这个包using namespace std;int main(){ ifstream ifs("C:\\test.txt"); ofstream ofs("C:\\test1.txt"); string s; // 读写一行数据,直到读写内容为空 while (getline(ifs, s) != NULL) { // 写入到文件 ofs << s << endl; } ofs.flush(); ofs.close(); ifs.close(); return 0;}]]></content>
<tags>
<tag>C++</tag>
</tags>
</entry>
<entry>
<title><![CDATA[队列的链式存储结构]]></title>
<url>%2F2018%2F05%2F10%2F%E9%98%9F%E5%88%97%E7%9A%84%E9%93%BE%E5%BC%8F%E5%AD%98%E5%82%A8%E7%BB%93%E6%9E%84%2F</url>
<content type="text"><![CDATA[算法实现123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110// 队头出队;队尾入队#include <stdio.h>#include <stdlib.h>#define OK 1#define OVERFLOW -2#define ERROR -1typedef int Status;typedef char QElemType;// 队列结点typedef struct QNode{ QElemType data; struct QNode *next;} QNode, *QNodePtr;// 链式队列typedef struct { QNodePtr front; QNodePtr rear;} LinkQueue;// 初始化队列Status InitQueue(LinkQueue *L){ // 创建头结点 QNode *head = (QNodePtr)malloc(sizeof(QNode)); if (head == NULL) { return OVERFLOW; } head->data = ' '; head->next = NULL; // 同时指向头结点 L->front = L->rear = head; return OK;}// 入队Status EnQueue(LinkQueue *L, QElemType e){ // 创建结点 QNode* node = (QNodePtr)malloc(sizeof(QNode)); if (!node) { return OVERFLOW; } node->data = e; node->next = NULL; // 尾指针指向该节点 L->rear->next = node; L->rear = node; return OK;}// 出队Status DeQueue(LinkQueue *L, QElemType *e){ // 判空 if (L->front == L->rear) { return ERROR; } QNode* p = L->front->next; // 保存元素 (*e) = p->data; // 删除元素 L->front->next = p->next; if (L->rear == p) { L->rear = L->front; } free(p); return OK;}void Traverse(LinkQueue L){ QNode* p = L.front->next; // 跳过头结点 while (p != NULL) { printf("%c ", p->data); p = p->next; }}int main(){ LinkQueue L; InitQueue(&L); EnQueue(&L, 'X'); EnQueue(&L, 'Y'); QElemType a; DeQueue(&L, &a); Traverse(L); return 0;}]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[关于高并发下的系统设计要点]]></title>
<url>%2F2018%2F05%2F07%2F%E5%85%B3%E4%BA%8E%E9%AB%98%E5%B9%B6%E5%8F%91%E4%B8%8B%E7%9A%84%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1%E8%A6%81%E7%82%B9%2F</url>
<content type="text"><![CDATA[对数据库更新操作。应该按条件查询数据,取出主键,按主键去更新数据。防止update操作进行全表锁定,影响了其他业务。 对已经使用了update操作的语句,尽可能给update的查询条件都加上索引,这样在更新时就不会全表锁住了。 通过redis实现锁的功能。比如通过redis锁定一张卡券,防止一张卡券被重复使用。 通过并发关键字synchronized保证线程的安全。 SimpleDateFormat对象为线程不安全的,所以不能静态new对象,应该是各个方法各自new该对象,不能静态共享。]]></content>
<tags>
<tag>高并发</tag>
</tags>
</entry>
<entry>
<title><![CDATA[关于系统重构的步骤梳理]]></title>
<url>%2F2018%2F05%2F06%2F%E5%85%B3%E4%BA%8E%E7%B3%BB%E7%BB%9F%E9%87%8D%E6%9E%84%E7%9A%84%E6%AD%A5%E9%AA%A4%E6%A2%B3%E7%90%86%2F</url>
<content type="text"><![CDATA[重构步骤 删除废弃的接口 业务功能的简单化和清晰化 删除数据库废弃的字段 由影响范围小到影响范围大的方向逐个进行重构比如先对某个功能进行重构,然后再对表结构进行更改。 统计该重构涉及的所有接口和业务功能包括调用和被调用之间的所有接口。 针对该重构的功能写测试案例1、对该重构涉及的所有的接口,写对应的测试案例,理论上应该覆盖所有被影响的接口。2、对该重构涉及的所有业务功能,写对应的测试案例。 从底层系统向上层系统逐一重构系统有调用和被调用之间的关系,应该先重构被调用的系统,然后再重构调用系统。并且每重构完一个接口,应该有对应的单元测试覆盖该接口,测试通过后,再重构下一个接口。 所有业务功能的测试系统接口层测试全部完毕后,对业务功能进行整体的测试。 推送到测试环境推送到测试环境,给测试人员进行测试。为了确保重构的可靠性,应该在测试环境跑2个星期没问题后,再推上生产。]]></content>
<tags>
<tag>系统重构</tag>
<tag>Refactoring</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hexo博客添加站内搜索页]]></title>
<url>%2F2018%2F05%2F04%2FHexo%E5%8D%9A%E5%AE%A2%E6%B7%BB%E5%8A%A0%E7%AB%99%E5%86%85%E6%90%9C%E7%B4%A2%E9%A1%B5%2F</url>
<content type="text"><![CDATA[安装 hexo-generator-search在站点的根目录下执行以下命令:1$ npm install hexo-generator-search --save 安装 hexo-generator-searchdb1$ npm install hexo-generator-searchdb --save 在 blog/source 目录下会有一个新生成search.xml文件。 创建搜索页面在站点的根目录下执行以下命令:1$ hexo new page "search" 在 blog/source 下会新生成一个新的文件夹search,在该文件夹下会有一个index.md文件。 注意:修改该文件,在文章倒数第2行插入一行1type: "search" 修改站点配置文件修改blog下的_config.yml文件12345search: path: search.xml field: post format: html limit: 10000 修改 /blog/themes/xxx 下的_config.yml文件12local_search: enable: true 重新部署,启动1$ hexo clean; hexo g; hexo s;]]></content>
</entry>
<entry>
<title><![CDATA[Spring Cloud 整体架构设计介绍]]></title>
<url>%2F2018%2F05%2F03%2Fspring-cloud-start%2F</url>
<content type="text"><![CDATA[Spring Cloud 包含组件:Eureka、Ribbon、Hystrix、Zuul、Spring-Cloud-Config Spring Cloud 微服务架构图,如下图所示。 Eureka服务注册与发现注册中心。 Ribbon服务调用端负载均衡负责负载均衡的计算。 Hystrix服务调用端熔断Hystrix熔断机制,每一个微服务都有熔断处理。 Zuul代理机制路由规则(路径映射),对名称进行隐藏。 Spring Cloud Config服务配置组件基于git进行配置的管理。 Zipkin链路跟踪工具作用是监控微服务集群中调用链路的通畅情况。]]></content>
<tags>
<tag>Spring Cloud</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Lucene全文检索工具]]></title>
<url>%2F2018%2F05%2F03%2FLucene%E5%85%A8%E6%96%87%E6%A3%80%E7%B4%A2%E5%B7%A5%E5%85%B7%2F</url>
<content type="text"><![CDATA[Lucene是基于Java的全文信息检索工具包。 索引创建与检索创建索引 需要检索的数据(Document) 分词技术(Analyzer) 索引创建(Indexer) 索引检索 搜索关键词(keywords) 分词技术 (Analyzer) 检索索引(Search) 返回结果 Lucene文件结构 索引(Index):一个索引放在一个文件夹中。 段(Segment):一个索引中可以有很多段,段与段之间是独立的,添加新的文档可以产生新段,不同的段可以合并成一个新段。 文档(Document):文档是创建索引的基本单位,不同的文档保存在不同的段中,一个段可以包含多个文档。 域(Field):一个文档包含不同类型的信息,可以拆分开索引。 词(Term):词是索引的最小单位,是经过词法分析和语言处理后的数据。 正向信息就是按层次保存了索引一直到词的包含关系:索引 > 段 > 文档 > 域 > 词反向信息:词 > 文档 其他Lucene索引查看工具:Luke]]></content>
<tags>
<tag>全文检索</tag>
<tag>lucene</tag>
</tags>
</entry>
<entry>
<title><![CDATA[栈]]></title>
<url>%2F2018%2F05%2F02%2F%E6%A0%88%2F</url>
<content type="text"><![CDATA[算法描述InitStack(*S)操作步骤:申请空间,底部和顶部指针都指向该空间 IsFull(S)操作步骤:(栈顶指针-栈底指针) >= 申请的长度 Push(*S,e)操作步骤:判满(//如果满了。重新申请空间;修改顶部指针;修改size长度);栈顶插入e;栈顶++ 算法实现123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081#include <stdio.h>#include <stdlib.h>#define INIT_SIZE 10#define INCREAME 10typedef char SElemType;// 存储结构typedef struct Stack{ char* base; // 底部指针 char* top; // 顶部指针 int size; // 申请的长度} Stack;// 初始化栈int InitStack(Stack *S){ S->base = S->top = (SElemType *)malloc(sizeof(SElemType) * INIT_SIZE); if (!S->base) { return -2; } S->size = INIT_SIZE; return 1;}// 插入元素int Push(Stack *S, SElemType e){ int length = (S->top - S->base) / sizeof(SElemType); SElemType * p; if (length >= S->size) { p = (SElemType *)realloc(S->base, sizeof(SElemType) * (S->size + INCREAME)); if (!p) { return -2; } S->base = p; S->top = S->base + S->size; // 修改顶部指针指向新的位置 S->size += INCREAME; } *(S->top) = e; (S->top)++; return 1;}// 打印// 直接传值,不会改变Svoid Print(Stack S){ while (S.base <= S.top) { printf("%c", *(S.base)); S.base++; }}int main(){ Stack S; InitStack(&S); Push(&S, '1'); Push(&S, '2'); Push(&S, '3'); Push(&S, '4'); Push(&S, '5'); Push(&S, '6'); Push(&S, '7'); Push(&S, '8'); Push(&S, '9'); Push(&S, '0'); Push(&S, 'A'); Print(S); return 0;}]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[T-SQL语法示例]]></title>
<url>%2F2018%2F05%2F02%2FT-SQL%E8%AF%AD%E6%B3%95%E7%A4%BA%E4%BE%8B%2F</url>
<content type="text"><![CDATA[创建库123456789101112131415161718192021222324<begin>--创建数据库use master --使用SQL原有模板master进行创建go--创建一个名为yy_db的数据库,数据库命名最好添加_dbcreate database yy_db --数据文件的具体描述on primary ( name='yy_db.mdf', --创建主文件名字,名字要与数据库名字一样 filename='D:\Twins\Database\File\yy_db.mdf', --保存路径 size=3MB, --初始文件大小 --maxsize=60MB,最大限制 filegrowth=1MB --空间不足时,自动增长)--日志文件的具体描述log on ( name='yy_db.ldf', --创建日志文件名字 filename='D:\Twins\Database\File\yy_db.ldf', --保存路径 size=1MB, --初始文件大小 filegrowth=10% --空间不足,自动增长)<end> 创建表1234567891011121314151617181920212223242526272829303132333435363738394041424344454647--指定插入表格的数据库use yy_dbgo--创建一个表格,表格名字应该带有_tb后缀create table info_tb( --创建一个标识列和主键 Id int not null identity(1,1) constraint pk_info primary key, --创建一个唯一键,学生名字 Name nvarchar(20) not null --属于约束之一,应该起个名字 constraint un_info unique, --唯一单词unique --创建一个地址栏,默认是"广州",允许为空 Address nvarchar(30) null --属于默认约束,应该命名 constraint df_Address default '广州', --创建一个Email邮箱的,允许为空 Email nvarchar(30) null --属于约束中的一种,加上constraint constraint ck_Email --约束语句check(条件) check(Email like '%@%[.com .cn]'))create table score_tb ( --表格名字一定要加_tb id int not null identity (1,1) constraint pk_Id primary key , --创建一个外键 infoId int not null --命名外键名称 constraint fk_infoId --创建外键foreign key references 表名(列名) --引用是复数:references foreign key references info_tb(id), score float not null --创建检查约束 constraint ck_score check (score>=0 and score<=100),) 插入数据123456789--插入(insert)单行数据insert into info_tb (Name,Address,Email)values ('张三',default,'123@qq.com')--插入多行数据(微软官网)insert into info_tb (Name,Address,Email)values ('李四','杭州','2345@qq.com'), --逗号分隔,继续下一行数据('王五','武汉','3456@qq.com') 更新数据123--更改(update)数据update info_tb set Email='5678@qq.com'where Email='123@qq.com' 删除数据12--删除数据delete info_tb where Id=1 清空数据12--清空数据(truncate table)truncate table score_tb]]></content>
<tags>
<tag>T-SQL</tag>
<tag>sql server</tag>
<tag>SQL</tag>
</tags>
</entry>
<entry>
<title><![CDATA[golang的命名规范]]></title>
<url>%2F2018%2F05%2F02%2Fgolang%E7%9A%84%E5%91%BD%E5%90%8D%E8%A7%84%E8%8C%83%2F</url>
<content type="text"><![CDATA[类变量函数公有函数的名字以大写字母开头;私有函数的名字以小写字母开头。]]></content>
<tags>
<tag>goland</tag>
<tag>命名规范</tag>
</tags>
</entry>
<entry>
<title><![CDATA[golang入门过程遇到各种坑]]></title>
<url>%2F2018%2F05%2F02%2Fgolang%E5%85%A5%E9%97%A8%E8%BF%87%E7%A8%8B%E9%81%87%E5%88%B0%E5%90%84%E7%A7%8D%E5%9D%91%2F</url>
<content type="text"><![CDATA[1、go get xxx报错 unrecognized import path “golang.org/x/net/context”解决问题:http://www.jyguagua.com/?p=30082、连接数据库报错信息123452018/05/02 13:12:36 http: panic serving 127.0.0.1:60012: runtime error: invalid memory address or nil pointer dereferencegoroutine 6 [running]:net/http.(*conn).serve.func1(0xc042050820) G:/Go/src/net/http/server.go:1726 +0xd7... 可能的解决方案: 方案一:新增导入包 import (_ “github.com/go-sql-driver/mysql”) 方案二:检查数据库配置信息是否正确(用户名、密码等)]]></content>
<tags>
<tag>golang</tag>
<tag>go</tag>
<tag>入门</tag>
</tags>
</entry>
<entry>
<title><![CDATA[使用IntelliJ IDEA + Go插件快速搭建第一个Web程序]]></title>
<url>%2F2018%2F05%2F01%2Fidea-go-plugin-with-web%2F</url>
<content type="text"><![CDATA[配置golang环境配置本地仓库本地新建一个仓库:E:\go\Repository\src配置GOPATH路径为:E:\go\Repository(注意:不用配置 \src) 配置项目路径本地新建项目路径:E:\work_golang\src配置GOPATH路径为:E:\work_golang(注意:不用配置 \src)作用:配置了该路径项目才可以引用本地的包。 IntelliJ IDEA安装Golang插件注:可能低版本的IDEA不支持该插件,需要安装更新版本才能搜索到这个插件。IDEA安装Go插件 创建第一个Web项目环境描述 Windows 7 IntelliJ IDEA 2018.03 IDEA创建项目第一步:创建一个Go项目第二步:把项目代码替换成Web程序代码第三步:访问地址 http://localhost:8080/ 查看结果即可 部署程序Windows打包linux程序参考链接:https://blog.csdn.net/panshiqu/article/details/537880671234SET CGO_ENABLED=0SET GOOS=linuxSET GOARCH=amd64go build -o <out_file> <main_file> linux安装Go环境参考链接:https://medium.com/@patdhlk/how-to-install-go-1-9-1-on-ubuntu-16-04-ee64c073cd79 linux修改为可执行文件1chmod +x <file_name> linux后台运行go程序1nohup ./moment &]]></content>
<tags>
<tag>golang</tag>
<tag>go</tag>
</tags>
</entry>
<entry>
<title><![CDATA[自考中大实践课程【归档】]]></title>
<url>%2F2018%2F04%2F30%2F%E8%87%AA%E8%80%83%E4%B8%AD%E5%A4%A7%E5%AE%9E%E8%B7%B5%E8%AF%BE%E7%A8%8B%E3%80%90%E5%BD%92%E6%A1%A3%E3%80%91%2F</url>
<content type="text"><![CDATA[实践样题 数据结构 操作系统 软件工程 C++程序设计 数据库系统原理 Java语言程序设计 高级语言程序设计 C++快速入门 tutorial spoint 教程 数据库系统原理 T-SQL语法示例 数据结构【线性表】 线性表的顺序存储 线性表的链式存储结构 【栈】 栈 【队列】 队列的链式存储结构 循环队列 【树】 二叉树 【图】 无向图的邻接表存储 【查找】 二分法查找 【排序】 冒泡排序(含快速排序) 插入排序(含希尔排序) 选择排序(含堆排序) 归并排序 基数排序 桶排序(箱排序) 计数排序 各种排序算法比较]]></content>
<tags>
<tag>归档</tag>
<tag>自考</tag>
<tag>中山大学</tag>
<tag>计算机及应用</tag>
</tags>
</entry>
<entry>
<title><![CDATA[计数排序]]></title>
<url>%2F2018%2F04%2F30%2F%E8%AE%A1%E6%95%B0%E6%8E%92%E5%BA%8F%2F</url>
<content type="text"><![CDATA[基本概念 计数排序 (Counting sort)是一种算法复杂度O(n)的排序方法,适合于小范围集合的排序。 案例分析假设我们有[1,2,3,1,0,4]这6个数,范围是0~4,我们就取出5个箱子,箱子的编号就是代表原数组的元素。分配数字到各个箱子。分配完了后,0号箱有1个元素;1号箱有2个元素,2号箱有1个元素,2号箱有1个元素,4号箱有1个元素。然后依次取出箱的元素,放在新的数组,排序结束。]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[桶排序(箱排序)]]></title>
<url>%2F2018%2F04%2F30%2F%E6%A1%B6%E6%8E%92%E5%BA%8F%EF%BC%88%E7%AE%B1%E6%8E%92%E5%BA%8F%EF%BC%89%2F</url>
<content type="text"><![CDATA[算法原理桶排序(Bucket sort)或所谓的箱排序的原理是将数组分到有限数量的桶子里边,然后对每个桶再分别排序,最后将各个桶的数据有序的合并起来。 视频图解链接:https://www.cs.usfca.edu/~galles/visualization/BucketSort.html 案例分析设有数组[29, 25, 3, 49, 9, 37, 21, 43],那么数组中最大数为 49,可以设置5个桶,那么每个桶可存放数的范围为:0~9、10~19、20~29、30~39、40~49。然后分别将这些数放人自己所属的桶,如下图所示。]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[线性表的顺序存储]]></title>
<url>%2F2018%2F04%2F27%2F%E7%BA%BF%E6%80%A7%E8%A1%A8%E7%9A%84%E9%A1%BA%E5%BA%8F%E5%AD%98%E5%82%A8%2F</url>
<content type="text"><![CDATA[存储示意图 算法描述InitList(*L) 操作结果:构造一个空的线性表。 InsertElem(*L, i, e) 初始条件:线性表L存在;1 <= i <= ListLength(L) + 1 操作步骤:判满;从后往前移出第i个位置;L的长度 + 1 算法实现123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293#include <stdio.h>#include <stdlib.h>#define INIT_SIZE 10#define INCREASE_SIZE 5typedef int DataType;// 线性表的顺序存储结构typedef struct{ DataType *data; // 元素数组 int size; // 分配的长度 int length; // 当前长度}SqList;// 初始化线性表int InitList(SqList *L){ L->data = (DataType*)malloc(INIT_SIZE * sizeof(DataType)); if (!L->data) { return -1; } L->size = INIT_SIZE; L->length = 0; return 1;}// 在第i个位置插入元素int InsertElem(SqList *L, int i, DataType e){ if (i <= 0) { return -1; } // 顺序表已满 if (L->length >= L->size) { // 重新申请空间 // realloc(源地址, 新的空间) DataType* newList; newList = (DataType*)realloc(L->data, (L->length + INCREASE_SIZE) * sizeof(DataType)); if (!L->data) { return -1; } L->data = newList; // 修改分配的长度 L->size = L->length + INCREASE_SIZE; } // 在第i个位置插入 // i从1开始的,不是从0 i = i - 1; for (int j = L->length - 1; j >= i; j--) { // 移动元素 L->data[j + 1] = L->data[j]; } L->data[i] = e; L->length++; return 1;}int main(){ SqList L; InitList(&L); InsertElem(&L, 1, 1); InsertElem(&L, 1, 2); InsertElem(&L, 1, 3); InsertElem(&L, 1, 4); InsertElem(&L, 1, 5); InsertElem(&L, 1, 5); InsertElem(&L, 1, 5); InsertElem(&L, 1, 5); InsertElem(&L, 1, 5); InsertElem(&L, 1, 5); InsertElem(&L, 1, 5); InsertElem(&L, 1, 5); InsertElem(&L, 1, 1); InsertElem(&L, 1, 2); InsertElem(&L, 1, 3); InsertElem(&L, 1, 4); for (int i = 0; i < L.length; i++) { printf("%d ", L.data[i]); } return 0;}]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[循环队列]]></title>
<url>%2F2018%2F04%2F27%2F%E5%BE%AA%E7%8E%AF%E9%98%9F%E5%88%97%2F</url>
<content type="text"><![CDATA[基本概念顺序图 的各种存储情况,如下图所示。如果使用顺序表作为队列的话,当处于上图的最右图状态时,不能再继续插入元素,否则会因为数组越界而导致程序异常。假溢出:队列中还有可用的空间,却无法使用。 由此产生了由链表实现的 循环队列 ,只有队列未满时才可以插入新的队尾元素。 循环队列 (Circular Queue)的存储结构,如下图所示。 简单描述: 入队时,尾指针Q.rear追上头指针Q.front,队列已满。 出队时,头指针Q.front追上尾指针Q.rear,队列为空。 算法描述InitQueue(*Q)操作步骤:申请内存空间;头尾指针都指向0位置 IsFull(Q)操作步骤:(尾指针 + 1) % 队列长度 == 头指针 EnQueue(Q, e)操作步骤:判满;设置元素;尾指针 + 1 算法实现12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485// 队列:尾部插入,头部删除#include <stdio.h>#include <stdlib.h>#define QUEUE_SIZE 100#define OVERFLOW -2#define ERROR -1#define OK 1typedef int DataType;// 数据结构typedef struct{ DataType *data; // 存放元素 int front, rear; // 头指针,尾指针} CircleQueue;// 初始化队列// 头指针和尾指针都指向第0个元素int InitQueue(CircleQueue *Q){ // 申请内存空间 Q->data = (DataType *)malloc(QUEUE_SIZE * sizeof(DataType)); if (!Q->data) { return ERROR; } Q->front = Q->rear = 0; return OK;}// 少用一个元素空间,也即是尾指针指向的元素始终为空// 队列是否已满int IsFull(CircleQueue *Q){ return (Q->rear + 1) % QUEUE_SIZE == Q->front;}// 是否为空队列int IsEmpty(CircleQueue *Q){ return Q->front == Q->rear;}// 入队int EnQueue(CircleQueue *Q, DataType e){ // 判断队列是否已满 if (IsFull(Q)) { return OVERFLOW; } // 设置元素值 Q->data[Q->rear] = e; // 尾指针向前移动一位 Q->rear = (Q->rear + 1) % QUEUE_SIZE; return OK;}int main(){ // 创建队列 CircleQueue Q; InitQueue(&Q); // 入队 for (int i = 0; i < 10; i++) { EnQueue(&Q, i); } // 打印 DataType *data = Q.data; int k = Q.front; while (k % QUEUE_SIZE != Q.rear) { printf("%d ", data[k]); k++; } return 0;}]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[基数排序]]></title>
<url>%2F2018%2F04%2F25%2F%E5%9F%BA%E6%95%B0%E6%8E%92%E5%BA%8F%2F</url>
<content type="text"><![CDATA[基数排序 是一种借助多关键字排序的思想对单逻辑关键字进行排序的方法。个位数分类后各个桶的情况,如下图所示。12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667#include <stdio.h>#include <stdlib.h>#include <math.h>// 取指定位数的数字// position是数位int getPositionNum(int num, int position){ return (int)(num / pow(10.0, position - 1)) % 10;}// bitNum是数位个数// n是数字个数void RadixSort(int *arr, int bitNum, int n){ int radix = 10; int *count, *bucket, i, j, k; // 初始化10个桶,每个桶有各自编号,编号是0~9,分别对应数位数字。桶装的是各个数位数字的个数 count = (int *) malloc(sizeof(int) * radix); // bucket = (int *) malloc(sizeof(int) * n); for (int k = 1; k <= bitNum; k++) { // 初始化各个桶为0个 for (int i = 0; i < radix; i++) { count[i] = 0; } // 统计第k个数位数字的个数 for (int i = 0; i < n; i++) { // 查询第k位存放的数字 int num = getPositionNum(arr[i], k); // 该数字的数量 + 1 count[num]++; } for (int i = 1; i < radix; i++) { count[i] = count[i] + count[i - 1]; } for (int i = n - 1; i >= 0; i--) { j = getPositionNum(arr[i], k); bucket[count[j] - 1] = arr[i]; count[j]--; } for (int i = 0, j = 0; i < n; i++, j++) { arr[i] = bucket[j]; } }}int main(){ int arr[] = {1,3,4,6}; RadixSort(arr, 1, 4); for (int i = 0; i < 4; i++) { printf("%d ", arr[i]); } return 0;}]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[归并排序]]></title>
<url>%2F2018%2F04%2F25%2F%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F%2F</url>
<content type="text"><![CDATA[算法描述MergeSort(int *array, int low, int high)方法第一步:拆分第二步:左半部分递归拆分第三步:右半部分递归拆分第四步:调用方法Merge()进行排序和合并 Merge(int *array, int low, int mid, int high)方法第一步:新建一个临时数组第二步:分别从左右两边有序取数据,插入到新的数组第三步:复制新数组的内容(下标0~length)到原数组(下标low~high)中 图解归并排序分割和合并过程,如下图所示。 算法实现1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768#include <stdio.h>#include <stdlib.h>// 按顺序进行合并2个有序区void Merge(int *source, int low, int mid, int high){ int i = low, j = mid + 1, p = 0; int *target; // 合并后的有序区 target = (int *) malloc(sizeof(int) * (high - low + 1)); if (!target) { return; } // i > mid || j > high 条件成立时,结束 while (i <= mid && j <= high) { // 如果第i个元素 <= 第j个元素,则取小的元素出来,并且自增一位 target[p++] = (source[i] <= source[j]) ? source[i++] : source[j++]; } // 左半部分未遍历完 while (i <= mid) { target[p++] = source[i++]; } // 右半部份未遍历完 while (j <= high) { target[p++] = source[j++]; } // 把结果复制到原数组中 // p是从第0个下标开始插入元素的 p = 0; for (i = low; i <= high; i++, p++) { source[i] = target[p]; }}// 第一步:拆分// 第二步:左半部分递归拆分// 第三步:右半部分递归拆分// 第四步:排序并且合并void MergeSort(int *source, int low, int high){ // 用分治法对source[low...high]进行二路归并 int mid; if (low < high) { mid = (low + high) / 2; // 一分为二 MergeSort(source, low, mid); // 左半部分一分为二,进行排序 MergeSort(source, mid + 1, high); // 右半部份一分为二,进行排序 Merge(source, low, mid, high); // 将2个有序区合并成一个有序区 }}int main(){ int arr [] = {4,5,2,1}; MergeSort(arr, 0, 3); for (int i = 0; i < 4; i++) { printf("%d ", arr[i]); } return 0;}]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[C++基础入门]]></title>
<url>%2F2018%2F04%2F25%2Fcplusplus%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8%2F</url>
<content type="text"><![CDATA[1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980// 标准库头文件#include <iostream>// 使用命名空间概念using std::cout;using std::endl;int outBool(){ bool isAlpha; isAlpha = false; if (!isAlpha) { // 默认是以0或1输出布尔值 std::cout << "isAlpha = " << isAlpha << std::endl; // 以true或false输出布尔值 std::cout << std::boolalpha << "isAlpha = " << isAlpha << std::endl; } return 0;}// 定义全局变量// int v1 = 20;// 变量的引用作为参数传入,调用时只需要传入普通变量即可void swap(int& a, int& b){ int t; t = a; a = b; b = t;}int main(){ // 输出Aloha world! // endl是输出换行意思 // cout << "Aloha world!" << endl; // 显式转换数据类型static_case<double> // cout << static_cast<double>(1) / 2 << endl; // int v1 = 5; // cout << "打印局部变量值 = " << v1 << endl; // :: 打印全局变量 // cout << "打印全局变量值 = " << ::v1 << endl; // inline内联函数 // 如 inline int max(int a, int b) {} // 引用作为参数 /*int a1 = 10; int a2 = 20; cout << "交换前:a1 = " << a1 << " a2 = " << a2 << endl; swap(a1, a2); cout << "交换后:a1 = " << a1 << " a2 = " << a2 << endl;*/ // C++创建对象 // 创建一个char对象,并且初始值是97 // char* s = new char(97); // 创建一个长度为10的数组对象 // int* p = new int[10]; // C++ 定义常量 //const int ARRAY_SIZE = 10; //int arr[ARRAY_SIZE]; //int x = 1; // 定义常量指针 //const int* p1; //p1 = &x; // *p1 = 10; // 定义指针常量 //int* const p2 = &x; //int y = 10; //p2 = &y; // const在前先读,const在前不变 return 0;}]]></content>
<tags>
<tag>C++</tag>
</tags>
</entry>
<entry>
<title><![CDATA[选择排序(含堆排序)]]></title>
<url>%2F2018%2F04%2F24%2F%E9%80%89%E6%8B%A9%E6%8E%92%E5%BA%8F%EF%BC%88%E5%90%AB%E5%A0%86%E6%8E%92%E5%BA%8F%EF%BC%89%2F</url>
<content type="text"><![CDATA[直接选择排序基本思想第一趟:在所有元素中选出最小元素。把它和第1个元素进行位置交换。第二趟:在第2个元素 到 最后一个元素中,选出最小元素。把它和第2个元素交换。…依次类推,直到最后一个元素。 算法图解 算法实现12345678910111213141516171819202122232425262728293031323334353637383940414243#include <stdio.h>#include <stdlib.h>// 简单选择排序// 基本思想:通过n - 1次数据元素的比较,从n - i + 1个记录中选择最小的数据,并与第i个数据进行交换int SelectSort(int * arr, int n){ // 遍历n - 1次就可以了 for (int i = 0; i < n - 1; i++) { // 假定第一个为最小值 int min = arr[i], minIndex = i; // 从第二个数开始取 for (int j = i + 1; j < n; j++) { // 跟最小值比较。小了,则重新赋值 if (arr[j] < min) { minIndex = j; min = arr[minIndex]; } } // 把最小值移到有序序列的末端 arr[minIndex] = arr[i]; arr[i] = min; } return 0;}int main(){ int n = 10; int arr[10] = {54,675,635,5634,243, 432,13,341,132,341}; SelectSort(arr, n); for (int i = 0; i < n; i++) { printf("%d ", arr[i]); } return 0;} 堆排序基本概念堆排序是一种树形选择排序,在排序过程中可以把元素看成一颗完全二叉树,每个节点都大(小)于他的两个子结点。当每个节点都大于等于它的两个子结点时,称为大顶堆;否则为小顶堆。 算法实现1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374//堆排序(HeapSort) #include <stdio.h>#include <stdlib.h>//堆调整,构建大顶堆,arr[]是待调整的数组,i是待调整的数组 //元素的位置,length是数组的长度 void HeapAdjust(int arr[], int i, int length) { int Child; int temp; for (; 2 * i + 1 < length; i = Child) { //子节点的位置 = 2 * (parent(父结点)) + 1 Child = 2 * i + 1; //得到子结点中较大的结点 if(Child < length - 1 && arr[Child + 1] > arr[Child]) { ++Child; } //如果较大的子结点大于父结点那么把较大的子结点往上移动 //替换它的父结点 if(arr[i] < arr[Child]) { temp = arr[i]; arr[i] = arr[Child]; arr[Child] = temp; } else { break; } }}//堆排序算法 void HeapSort(int arr[], int length) { int i; //调整序列的前半部分元素,调整完之后第一个元素 //是序列的最大元素,length/2-1是最后一个非叶子结点 for (i = length / 2 - 1; i >= 0; --i) { HeapAdjust(arr, i, length); } //从最后一个元素开始对序列进行调整,不断的缩小调整 //的范围直到第一个元素 //循环里是把第一个元素和当前的最后一个元素交换 //保证当前的最后一个位置的元素是现在这个序列的最大的 //不断的缩小调整heap的范围,每一次调整完毕保证第一个 //元素是当前序列的最大的元素 for (i = length - 1; i > 0; --i) { arr[i] = arr[0]^arr[i]; arr[0] = arr[0]^arr[i]; arr[i] = arr[0]^arr[i]; HeapAdjust(arr, 0, i); //递归调整 }}int main() { int i; int num[] = {98, 48, 777, 63, 57, 433, 23, 1112, 1}; printf("待排序的数据是:"); for (i = 0; i < sizeof(num) / sizeof(int); i++) { printf("%d ", num[i]); } printf("\n"); HeapSort(num, sizeof(num) / sizeof(int)); printf("排序后的数据是:"); for (i = 0; i < sizeof(num) / sizeof(int); i++) { printf("%d ", num[i]); } printf("\n"); return 0;}]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[指针基本概念]]></title>
<url>%2F2018%2F04%2F24%2F%E6%8C%87%E9%92%88%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5%2F</url>
<content type="text"><![CDATA[12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182#include <stdio.h>#include <stdlib.h>// 指针的基本定义void PointerDefine(){ // 指针变量存放的另一种变量的地址 int a1 = 100; int a2 = 20; // 定义整形数据的指针变量 int *p1, *p2; // 把指针p1指向a1变量 p1 = &a1; p2 = &a2; printf("%p, %p\n", p1, p2); // 输出a1,a2所在内存中的地址 printf("%d, %d\n", *p1, *p2); // 输出p1,p2指向变量对应的值}// 编写程序,输入2个整数,按先大后小的顺序输出a和b// 思路:用指针的方法处理这个问题,不交换整形变量的值,而是交换指针变量的值void SwitchPointer(){ int a, b; printf("请输入2个整数:"); scanf("%d %d", &a, &b); int *pa = &a, *pb = &b; if (*pa < *pb) { int *p = pa; pa = pb; pb = p; } printf("由大到小输出2个值:%d %d", *pa, *pb);}// 指针变量作为函数参数。作用是将一个变量的地址传送到另一个函数中// 通过指针变量的传入,可以改变指针所指向的变量的值void Swap(int *p1, int *p2){ // 交换指针所指向变量的值 int temp = *p1; *p1 = *p2; *p2 = temp;}// 打印交换前和交换后的值void PrintSwap(){ int a = 111, b = 222; printf("交换前,a = %d,b = %d\n", a, b); Swap(&a, &b); printf("交换后,a = %d,b = %d\n", a, b);}// 输入3个整数a、b、c,要求按从大到小的顺序将他们输出,用函数实现// 用exchange函数改变这3个变量的值,用swap函数交换2个变量的值void exchange(int *p1, int *p2, int *p3){ if (*p1 < *p2) { Swap(p1, p2); } if (*p1 < *p3) { Swap(p1, p3); } if (*p2 < *p3) { Swap(p2, p3); }}int main(){ int a = 2, b = 2, c = 3; exchange(&a, &b, &c); printf("从大到小:%d %d %d\n", a, b, c); return 0;}]]></content>
<tags>
<tag>C语言</tag>
</tags>
</entry>
<entry>
<title><![CDATA[插入排序(含希尔排序)]]></title>
<url>%2F2018%2F04%2F24%2F%E6%8F%92%E5%85%A5%E6%8E%92%E5%BA%8F%EF%BC%88%E5%90%AB%E5%B8%8C%E5%B0%94%E6%8E%92%E5%BA%8F%EF%BC%89%2F</url>
<content type="text"><![CDATA[插入排序算法描述第三趟的算法描述:// 取出3// 和5比较,小了,5往后移一位// 和6比较,小了,6往后移一位// 发现没得比较了,元素插入到第0个位置 图解 直接插入排序 (Straight Insertion Sort)的排序过程,如下图所示。 算法实现123456789101112131415161718192021222324252627282930313233343536373839404142#include < stdio.h > #include < stdlib.h >void InsertSort(int array[], int length) { int i, temp, p; // 从第 2 个元素开始 for (i = 1; i < length; i++) { // 把第i个元素保存起来,以便留出空位给新的元素 temp = array[i]; // p保存了当前要比较的元素 p = i - 1; // 比第i个元素大的都要往后挪一位,直到(p < 0)为止 while (p >= 0 && temp < array[p]) { // 从后往前挪出空位 array[p + 1] = array[p]; p--; } // 插入 array[p + 1] = temp; }}int main() { int length; printf("请输入数组长度:"); scanf("%d", &length); int * array; array = (int *) malloc(sizeof(int) * length); printf("请输入数组(以逗号分隔):"); for (int i = 0; i < length; i++) { scanf("%d", &array[i]); } InsertSort(array, length); for (int i = 0; i < length; ++i) { printf("%d ", array[i]); } printf("\n"); return 0;} 希尔排序基本概念 希尔排序 (Shell’s Sort)是插入排序中的一种。循环地间隔一个grap取数进行插入排序,直到grap <= 0为止。排序过程如下图所示。 稳定性:不稳定(由于是跳跃性插入)时间复杂度:O(n^1.3)空间复杂度:O(1) 算法实现12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758#include <stdio.h>#include <stdlib.h>// 希尔排序int ShellSort(int * arr, int length){ int i, j, k; int temp, gap; // 初始步长为数组的一半 // 往后逐渐缩小为原来的一半 for (gap = length / 2; gap > 0; gap /= 2) { // 只需要遍历到一个步长即可 for (i = 0; i < gap; i++) { // 从步长的第2个元素开始 // 使用插入排序 for (j = i + gap; j < length; j += gap) { if (arr[j] < arr[j - gap]) { temp = arr[j]; k = j - gap; while (k >= 0 && arr[k] > temp) { arr[k + gap] = arr[k]; k -= gap; } arr[k + gap] = temp; } } } } return 1;}int main(){ int length; printf("请输入数组长度:"); scanf("%d", &length); int * arr = (int *) malloc(sizeof(int) * length); printf("请输入数字(以空格分隔):"); for (int i = 0; i < length; i++) { scanf("%d", &arr[i]); } ShellSort(arr, length); for (int i = 0; i < length; i++) { printf("%d\t", arr[i]); } return 0;}]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[冒泡排序(含快速排序)]]></title>
<url>%2F2018%2F04%2F23%2F%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F%EF%BC%88%E5%90%AB%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F%EF%BC%89%2F</url>
<content type="text"><![CDATA[冒泡排序基本概念 冒泡排序 的排序过程,如下图所示。 算法描述BubbleSort(arr, length)操作步骤:遍历(length - 1)趟。每一趟排序都是从前往后比较,无序队列中最大元素交换到最后。稳定性:稳定排序时间复杂度:O(n^2)空间复杂度:O(1) 算法实现1234567891011121314151617181920212223242526272829303132#include < stdio.h > #include < stdlib.h >void BubbleSort(int * arr, int length) { int round = 1; // 第 i 轮 int temp; // 临时值,用于交换 for (int i = 0; i < length - 1; i++) { for (int j = 0; j < length - round; j++) { if (arr[j + 1] < arr[j]) { // 交换位置 temp = arr[j + 1]; arr[j + 1] = arr[j]; arr[j] = temp; } } round++; }}int main() { int arr[10] = {2,1,0,1432,41,4321,314,-413,413,41}; int length = 10; BubbleSort(arr, length); for (int i = 0; i < length; i++) { printf("%d \t", arr[i]); } return 0;} 快速排序基本概念快速排序 是对冒泡排序的改进。第一趟排序,如下图所示。整体的排序过程,如下图所示。关键字:中位mid 算法描述QuickSort(* arr, low, high)操作步骤:递归地取第一个元素为参考,将元素划分成左、右两部分,直到头指针大于尾指针。稳定性:不稳定时间复杂度:O(nlog2n)空间复杂度:O(log2n) 算法实现1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950#include < stdio.h > #include < stdlib.h >// 快速排序// 参数:待排数组, 头指针, 尾指针void QuickSort(int * arr, int low, int high) { // 取出关键字 int key = arr[low]; // 递归结束条件 if (low > high) { return; } int head = low; int tail = high; while (tail > head) { // 比key大或等于key,则指针向前移 while ((arr[tail] >= key) && (tail > head)) { tail--; } // 比key小或等于key,则交换 arr[head] = arr[tail]; // 比key小或等于key,则指针向后移 while ((arr[head] <= key) && (tail > head)) { head++; } // 比key大,则交换 arr[tail] = arr[head]; } // 替换最后重合的值为key arr[head] = key; // 递归排序左半部分 QuickSort(arr, low, head - 1); // 递归排序右半部分 QuickSort(arr, tail + 1, high);}int main() { int arr[10] = {1,32,231,1,132,413,41,41,413,5443}; QuickSort(arr, 0, 9); for (int i = 0; i < 10; i++) { printf("%d ", arr[i]); } return 0;}]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[中大实践课程复习要点]]></title>
<url>%2F2018%2F04%2F23%2F%E4%B8%AD%E5%A4%A7%E5%AE%9E%E8%B7%B5%E8%AF%BE%E7%A8%8B%E5%A4%8D%E4%B9%A0%E8%A6%81%E7%82%B9%2F</url>
<content type="text"><![CDATA[如果半个小时未解决的算法,一定不要再沉迷,一定要看书籍,不能浪费时间了。]]></content>
</entry>
<entry>
<title><![CDATA[二分法查找]]></title>
<url>%2F2018%2F04%2F23%2F%E4%BA%8C%E5%88%86%E6%B3%95%E6%9F%A5%E6%89%BE%2F</url>
<content type="text"><![CDATA[二分法查找 (Binary Search)又称折半查找,它只适用于有序表的查找。 其查找过程:先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或找不到该记录为止。 二分法查找的过程,如下图所示。 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152#include <stdio.h>#include <stdlib.h>/** 二分法查找 **/int BinarySearch(int * arr, int key, int low, int high){ int mid; while (low <= high) { mid = (low + high) / 2; if (key == arr[mid]) { return mid; } else if (key < arr[mid]) { high = mid - 1; } else { low = mid + 1; } } return -1;}int main(){ int n, i, key, position; int * arr; printf("请输入有序数组的大小:"); scanf("%d", &n); arr = (int *) malloc(sizeof(int) * n); printf("请按升序输入数字:"); for (int i = 0; i < n; i++) { scanf("%d", &arr[i]); } printf("请输入要查找的数字:"); scanf("%d", &key); position = BinarySearch(arr, key, 0, n - 1); if (position >= 0) { printf("该数字是第%d个数字", (position + 1)); } else { printf("未查询到该数字"); } return 0;}]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[无向图的邻接表存储]]></title>
<url>%2F2018%2F04%2F22%2F%E6%97%A0%E5%90%91%E5%9B%BE%E7%9A%84%E9%82%BB%E6%8E%A5%E8%A1%A8%E5%AD%98%E5%82%A8%2F</url>
<content type="text"><![CDATA[邻接表 是图的一种链式存储结构。123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182#include <stdio.h>#include <stdlib.h>#define OK 1#define ERROR -1#define MAX_NUM 20#define OVERFLOW -2#define TRUE 1#define FALSE 0typedef int Status;typedef int QElemType;typedef char VexType;// 邻接表存储结构// 边结点typedef struct EdgeNode{ int adjvex; // 顶点的位置 struct EdgeNode *next; // 指向下一条边的指针} EdgeNode, *EdgeLink;// 顶点结点typedef struct VexNode{ VexType data; // 顶点数据 EdgeNode *firstEdge; // 指向第一条依附该顶点的边的指针} VexNode, AdjList[20];// 图typedef struct ALGraph{ AdjList adjList; int vexNum, edgeNum; // 顶点数和边数} ALGraph;// 创建图Status CreateGraph(ALGraph *G){ int i, j, k; EdgeLink e; printf("请输入顶点数目和边数:\n"); scanf("%d", &(G->vexNum)); scanf("%d", &(G->edgeNum)); printf("请输入各顶点的数据:\n"); for (i = 0; i < G->vexNum; i++) { scanf("%c", &(G->adjList[i].data)); // 回车时继续 if (G->adjList[i].data == '\n') { i--; continue; } G->adjList[i].firstEdge = NULL; } printf("请依次输入边<Vi,Vj>的顶点序号:\n"); for(k = 0; k < G->edgeNum; k++) { scanf("%d", &i); scanf("%d", &j); // 边的第一个顶点 e = (EdgeLink) malloc(sizeof(EdgeNode)); // 初始化一个边结点 e->adjvex = j; // 顶点位置 e->next = G->adjList[i].firstEdge; // 指向下一条边的指针 G->adjList[i].firstEdge = e; // 边的第二个顶点 e = (EdgeLink) malloc(sizeof(EdgeNode)); // 初始化一个边结点 e->adjvex = i; // 顶点位置 e->next = G->adjList[j].firstEdge; // 指向下一条边的指针 G->adjList[j].firstEdge = e; } return OK;}// 队列存储结构(用于图的遍历)typedef struct QNode{ QElemType data; // 结点的数据 struct QNode *next; // 指向下一个结点} QNode, *QueuePtr;typedef struct{ QueuePtr front; // 队头指针 QueuePtr rear; // 队尾指针} LinkQueue;// 初始化队列Status initQueue(LinkQueue *Q){ QueuePtr head = (QNode*) malloc(sizeof(QNode)); if (!head) { return OVERFLOW; } Q->front = head; Q->rear = head; // 置空队尾的指向 Q->front->next = NULL; return OK;}// 入队Status enQueue(LinkQueue *Q, QElemType e){ // 申请一个结点 QueuePtr node = (QNode*) malloc(sizeof(QNode)); if (!node) { return OVERFLOW; } node->data = e; node->next = NULL; // 置空队尾指向空,在遍历时需要用到的 Q->rear->next = node; Q->rear = node; return OK;}// 只能从队头出队Status deQueue(LinkQueue *Q, QElemType *e){ // 判断是否有元素 if (Q->front == Q->rear) { return ERROR; } // 改队头指针 // 谨记:队列头部是有一个空值的头指针的 QueuePtr p = Q->front->next; *e = p->data; Q->front->next = p->next; // 判断当前是否是最后一个元素了 if (Q->rear == p) { Q->rear = Q->front; } free(p); return OK;}int visited[20]; // 用于记录状态// 递归从第i个结点深度优先遍历图void DFS(ALGraph G, int i){ EdgeLink p; visited[i] = TRUE; printf("%c\t", G.adjList[i].data); p = G.adjList[i].firstEdge; while (p) { if (!visited[p->adjvex]) { DFS(G, p->adjvex); } p = p->next; }}// 深度优先遍历图Status DFSTraverse(ALGraph G){ int i; for (i = 0; i < MAX_NUM; i++) { visited[i] = FALSE; } for (i = 0; i < G.vexNum; i++) { if (!visited[i]) { DFS(G, i); } } return OK;}int main(){ ALGraph G; CreateGraph(&G); DFSTraverse(G); return 0;}]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[二叉树]]></title>
<url>%2F2018%2F04%2F21%2F%E4%BA%8C%E5%8F%89%E6%A0%91%2F</url>
<content type="text"><![CDATA[基本概念二叉树创建过程,如下图所示。程序输入和输出过程,如下图所示。 算法描述创建二叉树:CreateBiTree(*T)操作步骤:输入0,递归结束,树指向NULL;输入其他,创建结点,给结点赋值,递归地创建左子树,递归地创建右子树。 遍历树:Travel(T)操作步骤:树不为空,打印树存储值,递归地遍历左子树,递归地遍历右子树。 计算树最大深度:maxDepth(T)操作步骤:树为空,则返回0;树不为空,递归遍历左子树 + 1,递归遍历右子树 + 1,取左右树深度的较大者返回。 算法实现123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475#include < stdio.h > #include < stdlib.h >#define OK 1#define OVERFLOW - 2typedef int TElemType;typedef int Status;// 存储结构typedef struct BiTNode { TElemType data; struct BiTNode *lchild, *rchild; // 左子树 右子树} BiTNode, *BiTree;// 初始化一颗树// 问题:如何理解**T参数呢Status CreateBiTree(BiTree *T, char *desc) { TElemType e; printf("%s", desc); scanf("%d", &e); // 输入一个数 if (e == 0) { (*T) = NULL; } else { (*T) = (BiTree) malloc(sizeof(BiTNode)); if (!(*T)) { return OVERFLOW; } (*T)->data = e; // 左子树的地址的地址 CreateBiTree(&((*T)->lchild), "请输入左结点数据:"); // 创建左子树 CreateBiTree(&((*T)->rchild), "请输入右结点数据:"); // 创建右子树 } return OK;}// 前序遍历二叉树void Travel(BiTree T){ // 递归结束条件:指向数据为空 if (T != NULL) { printf("%d ", T->data); Travel(T->lchild); Travel(T->rchild); }}// 求二叉树的深度// 分别遍历左子树,右子树的深度,取最大值// 算法描述:遍历左右子树,取较大深度 + 1int maxDepth(BiTree T){ // 递归结束条件:树指向节点为空 if (T == NULL) { return 0; } int lDepth = maxDepth(T->lchild) + 1; int rDepth = maxDepth(T->rchild) + 1; return lDepth > rDepth ? lDepth : rDepth;}int main() { BiTree T; CreateBiTree(&T, "请输入根结点数据:"); printf("\n先序遍历输出二叉树序列:"); Travel(T); printf("\n该二叉树最大深度:%d", maxDepth(T)); return 0;}]]></content>
<categories>
<category>数据结构</category>
</categories>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
<tag>二叉树</tag>
<tag>链式结构</tag>
</tags>
</entry>
<entry>
<title><![CDATA[线性表的链式存储结构]]></title>
<url>%2F2018%2F04%2F21%2F%E7%BA%BF%E6%80%A7%E8%A1%A8%E7%9A%84%E9%93%BE%E5%BC%8F%E5%AD%98%E5%82%A8%E7%BB%93%E6%9E%84%2F</url>
<content type="text"><![CDATA[存储示意图线性表的链式存储的结点示意图,如下图所示。线性表的链式存储存储结构示意图,如下图所示。线性链表的数据结构,如下图所示。 算法描述InitList(*L) 操作步骤:创建头结点;L指向头结点 注意:初始化线性表传入参数为指针的指针 InsertElem(L,i,e) 初始条件:线性表L已存在;i >= 1 操作步骤:遍历找出第i位置;修改指针 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768#include < stdio.h > #include < stdlib.h >#define OVERFLOW -2#define ERROR 0#define OK 1#define ElemType int#define Status int// 存储结构typedef struct LNode { ElemType data; // 数据域 struct LNode * next; // 指针域,下一个结点的指针(next是结构体struct LNode的指针类型)} LNode, *LinkList;// 初始化线性表void InitList(LinkList * L) { // 线性表L的指针指向第一个元素 // LinkList *L == LNode** 是指针的指针 *L = (LinkList) malloc(sizeof(LNode)); // 申请一个结点的空间 if (!L) { exit(OVERFLOW); } (*L)->next = NULL; // 新链表的下一个元素指向NULL}// 插入元素Status InsertElem(LinkList L, int i, ElemType e) { int j = 0; // i是从1开始的,第1个元素是对应下标为0的元素 i = i - 1; LinkList s; LinkList p = L; // p不为空 while (p && j < i) { p = p->next; // 通过头指针去逐个遍历,找出i的位置 j++; } if (!p || j > i) { return ERROR; } s = (LinkList) malloc(sizeof(LNode)); // 新增一个结点 s->data = e; s->next = p->next; p->next = s; return OK;}// 遍历线性表void TraverseList(LinkList L) { LinkList p = L->next; while (p) { printf("%d\t", p->data); p = p->next; }}int main() { LinkList L; // 传入引用,需要修改L InitList(&L); InsertElem(L, 1, 10); TraverseList(L); return 0;}]]></content>
<tags>
<tag>C语言</tag>
<tag>数据结构</tag>
</tags>
</entry>
</search>