跳舞链解数独 静态数组优化

前几天有人问我之前写的那个跳舞链解数独的程序的内存泄漏问题如何解决,因此回顾了一下我的那个程序。现在看来那个程序简直不忍直视,于是大刀阔斧的改了。主要是把动态内存分配都改为了静态预分配,这样就可以避免频繁的调用malloc和free。同时静态分配的好处就是内存访问局部性比较好,cache不容易miss。而且在一行四个节点连续分配的情况下,就没有必要存储左右指针了。而且在连续分配的时候,指针都可以蜕变为数组索引,访问就比较简单了。还有一个好处就是整个程序可读性大大增强。现在这个版本的代码如下,利用http://staffhome.ecm.uwa.edu.au/~00013890/sudokumin.php中的测试文件,总耗时 16967ms.这个耗时是在不输出结果数独的情况下测试的,带输出的测试没有去做,屏幕太闪。整个代码如下,虽说刮着c++的招牌,其实全是c。。。

  1 #include <iostream>
  2 #include <vector>
  3 #include <stack>
  4 #include <map>
  5 #include <ctime>
  6 #include <fstream>
  7 using namespace std;
  8 #define shift_base 0x80000000
  9 struct basic_node
 10 {
 11     //这里之所以没有left和right是因为我们每次分配一行的时候,是四个点一起分的,所以可以直接通过加减1来搞定左右关系
 12     int down;
 13     int up;
 14     int column;
 15 };
 16 struct basic_node total_nodes[324 + 81 * 9 * 4];//324个头节点,81个格子,每个格子有9种情况,每种情况有四个点。
 17 int avail_node_index = 324;//分配节点时的编号
 18 int node_stack[81];
 19 int stack_index = 0;
 20 struct node_heap
 21 {
 22     int cul_value;//代表这个列中的1的个数
 23     int position_index;//代表着个点所指示的列的索引
 24 };
 25 struct node_heap mutual_index[324];//这个是堆
 26 int current_heap_number = 323;//这个是当前可用的堆中的节点数
 27 int available_column = 323;//这个是当前可用列数
 28 int position_index[324];//这个是列在堆中的位置
 29 int out[9][9] = { { 8, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 3, 6, 0, 0, 0, 0, 0 }, { 0, 7, 0, 0, 9, 0, 2, 0, 0 },  30 {0, 5, 0, 0, 0, 7, 0, 0, 0}, { 0, 0, 0, 0, 4, 5, 7, 0, 0 }, { 0, 0, 0, 1, 0, 0, 0, 3, 0 }, { 0, 0, 1, 0, 0, 0, 0, 6, 8 },  31 {0, 0, 8, 5, 0, 0, 0, 1, 0}, { 0, 9, 0, 0, 0, 0, 4, 0, 0 } };
 32
 33 void initial(void)
 34 {
 35     for (int i = 0; i < 324; i++)
 36     {
 37         total_nodes[i].column = i;
 38         total_nodes[i].down = i;
 39         total_nodes[i].up = i;
 40         mutual_index[i].cul_value= 0;
 41         mutual_index[i].position_index = i;
 42         position_index[i] = i;
 43     }
 44     stack_index = 0;
 45     available_column = 323;
 46     current_heap_number = 323;
 47     avail_node_index = 324;
 48 }
 49 void swap_heap(int index_one, int index_two)//交换在堆中的两个元素的值,及相关数据索引
 50 {
 51     int intermidate_one, intermidate_two;
 52     intermidate_one = mutual_index[index_one].cul_value;
 53     intermidate_two = mutual_index[index_one].position_index;
 54     mutual_index[index_one].cul_value = mutual_index[index_two].cul_value;
 55     mutual_index[index_one].position_index = mutual_index[index_two].position_index;
 56     mutual_index[index_two].cul_value = intermidate_one;
 57     mutual_index[index_two].position_index = intermidate_two;
 58     position_index[mutual_index[index_two].position_index] = index_two;
 59     position_index[mutual_index[index_one].position_index] = index_one;
 60 }
 61 void heap_initial()//初始化堆,这个动作是在所有的行插入完成之后做的
 62 {
 63     int k, i = 0;
 64     int current_min;
 65     for (i = (current_heap_number - 1) / 2; i >= 0; i--)
 66     {
 67         k = i;
 68         while (2 * k + 1 <= current_heap_number)
 69         {
 70             current_min = mutual_index[k].cul_value;
 71             current_min = current_min < mutual_index[2 * k + 1].cul_value ? current_min : mutual_index[2 * k + 1].cul_value;
 72             if (2 * k + 2 <= current_heap_number)
 73             {
 74                 current_min = current_min < mutual_index[2 * k + 2].cul_value ? current_min : mutual_index[2 * k + 2].cul_value;
 75             }
 76             if (current_min == mutual_index[k].cul_value)
 77             {
 78                 break;
 79             }
 80             else
 81             {
 82                 if (current_min == mutual_index[2 * k + 1].cul_value)
 83                 {
 84                     swap_heap(k, 2 * k + 1);
 85                     k = 2 * k + 1;
 86                 }
 87                 else
 88                 {
 89                     swap_heap(k, 2 * k + 2);
 90                     k = 2 * k + 2;
 91                 }
 92             }
 93         }
 94     }
 95 }
 96 void delete_minimal()//删除堆中最小的元素
 97 {
 98     int k;
 99     int current_min;
100     if (current_heap_number != 0)
101     {
102         swap_heap(0, current_heap_number);//交换最高元素与最低元素
103         current_heap_number--;//然后将堆的大小进行缩减
104         k = 0;
105         while (2 * k + 1 <= current_heap_number)//然后,下面便是一些维护性的工作,用来维护最小堆
106         {
107             current_min = mutual_index[k].cul_value;
108             current_min = current_min < mutual_index[2 * k + 1].cul_value ? current_min : mutual_index[2 * k + 1].cul_value;
109             if (2 * k + 2 <= current_heap_number)
110             {
111                 current_min = current_min < mutual_index[2 * k + 2].cul_value ? current_min : mutual_index[2 * k + 2].cul_value;
112             }
113             if (current_min == mutual_index[k].cul_value)
114             {
115                 return;
116             }
117             else
118             {
119                 if (current_min == mutual_index[2 * k + 1].cul_value)
120                 {
121                     swap_heap(k, 2 * k + 1);
122                     k = 2 * k + 1;
123                 }
124                 else
125                 {
126                     swap_heap(k, 2 * k + 2);
127                     k = 2 * k + 2;
128                 }
129             }
130         }
131     }
132     else//如果只剩下一个元素,那就不需要进行交换,直接将堆元素的个数降低一
133     {
134         current_heap_number = -1;
135     }
136 }
137 void heap_renew(int target_position, int new_value)//对于第target_position列,进行度数更新
138 {
139     int heap_target_position, k, current_min;
140     heap_target_position = position_index[target_position];//这个是这一列在堆中所在的位置
141     k = heap_target_position;
142     if (new_value < mutual_index[k].cul_value)//如果值是减少的,就直接进行赋值,然后维护堆的性质
143     {
144         mutual_index[k].cul_value = new_value;
145         while (k > 0 && (mutual_index[(k - 1) / 2].cul_value > mutual_index[k].cul_value))//维护堆
146         {
147             swap_heap((k - 1) / 2, k);
148             k = (k - 1) / 2;
149         }
150         if (new_value == 0)//如果是赋值为0,则从堆中进行删除,因为我们每次操纵一个元素,所以最多会有一个元素为0,所以肯定是最小值。
151         {
152             delete_minimal();
153         }
154     }
155     else//对于值增大的情况
156     {
157         mutual_index[k].cul_value = new_value;
158         if (new_value == 1)//如果新的值是1,则把这个元素重新加入堆中
159         {
160             current_heap_number++;//扩大堆的范围,我们可以证明重新加入堆中的元素一定是排在堆的末尾,当然条件是删除与插入的顺序是对应相反的
161             while (k > 0 && (mutual_index[(k - 1) / 2].cul_value > mutual_index[k].cul_value))//由于新的值是1,所以不可能比上一个数大
162             {
163                 swap_heap((k - 1) / 2, k);
164                 k = (k - 1) / 2;
165             }
166         }
167         else//如果不是1,说明已经在堆中,所以不需要扩大堆的范围,直接赋值之后进行维护堆结构就行
168         {
169             while (2 * k + 1 <= current_heap_number)
170             {
171                 current_min = mutual_index[k].cul_value;
172                 current_min = current_min < mutual_index[2 * k + 1].cul_value ? current_min : mutual_index[2 * k + 1].cul_value;
173                 if (2 * k + 2 <= current_heap_number)
174                 {
175                     current_min = current_min < mutual_index[2 * k + 2].cul_value ? current_min : mutual_index[2 * k + 2].cul_value;
176                 }
177                 if (current_min == mutual_index[k].cul_value)
178                 {
179                     break;
180                 }
181                 else
182                 {
183                     if (current_min == mutual_index[2 * k + 1].cul_value)
184                     {
185                         swap_heap(k, 2 * k + 1);
186                         k = 2 * k + 1;
187                     }
188                     else
189                     {
190                         swap_heap(k, 2 * k + 2);
191                         k = 2 * k + 2;
192                     }
193                 }
194             }
195         }
196     }
197 }
198 void node_heap_decrease(int node_index)//对于一个点进行她所在的行的删除,因为一行中一定有四个元素,所以有四列,我们对这四列的度数都进行减少1
199 {
200     int leftmost_node;//当前节点所在行的最左节点的索引
201     leftmost_node = node_index - (node_index % 4);
202     heap_renew(total_nodes[leftmost_node].column, mutual_index[position_index[total_nodes[leftmost_node].column]].cul_value -1);
203     leftmost_node++;
204     heap_renew(total_nodes[leftmost_node].column, mutual_index[position_index[total_nodes[leftmost_node].column]].cul_value -1);
205     leftmost_node++;
206     heap_renew(total_nodes[leftmost_node].column, mutual_index[position_index[total_nodes[leftmost_node].column]].cul_value -1);
207     leftmost_node++;
208     heap_renew(total_nodes[leftmost_node].column, mutual_index[position_index[total_nodes[leftmost_node].column]].cul_value -1);
209 }
210 void node_heap_increase(int node_index)//增加与减少的顺序是刚好相反的
211 {
212     int leftmost_node;//当前节点所在行的最右节点的索引
213     leftmost_node = node_index - (node_index % 4)+3;
214     heap_renew(total_nodes[leftmost_node].column, mutual_index[position_index[total_nodes[leftmost_node].column]].cul_value + 1);
215     leftmost_node--;
216     heap_renew(total_nodes[leftmost_node].column, mutual_index[position_index[total_nodes[leftmost_node].column]].cul_value + 1);
217     leftmost_node--;
218     heap_renew(total_nodes[leftmost_node].column, mutual_index[position_index[total_nodes[leftmost_node].column]].cul_value + 1);
219     leftmost_node--;
220     heap_renew(total_nodes[leftmost_node].column, mutual_index[position_index[total_nodes[leftmost_node].column]].cul_value + 1);
221 }
222 void insert_row(int current_row_index, int current_column_index, int value)
223 {
224     int current_leftmost = avail_node_index;
225     avail_node_index += 4;
226     int column_index;
227     column_index = current_row_index * 9 + value - 1;
228     total_nodes[current_leftmost].column = column_index;
229     total_nodes[current_leftmost].down = column_index;
230     total_nodes[current_leftmost].up = total_nodes[column_index].up;
231     total_nodes[total_nodes[column_index].up].down = current_leftmost;
232     total_nodes[column_index].up = current_leftmost;
233     mutual_index[column_index].cul_value++;
234     current_leftmost++;
235     column_index = 81 + current_column_index * 9 + value - 1;
236     total_nodes[current_leftmost].column = column_index;
237     total_nodes[current_leftmost].down = column_index;
238     total_nodes[current_leftmost].up = total_nodes[column_index].up;
239     total_nodes[total_nodes[column_index].up].down = current_leftmost;
240     total_nodes[column_index].up = current_leftmost;
241     mutual_index[column_index].cul_value++;
242     current_leftmost++;
243     column_index= 162 + ((current_row_index / 3) * 3 + current_column_index / 3) * 9 + value - 1;
244     total_nodes[current_leftmost].column = column_index;
245     total_nodes[current_leftmost].down = column_index;
246     total_nodes[current_leftmost].up = total_nodes[column_index].up;
247     total_nodes[total_nodes[column_index].up].down = current_leftmost;
248     total_nodes[column_index].up = current_leftmost;
249     mutual_index[column_index].cul_value++;
250     current_leftmost++;
251     column_index = 243 + current_row_index * 9 + current_column_index;
252     total_nodes[current_leftmost].column = column_index;
253     total_nodes[current_leftmost].down = column_index;
254     total_nodes[current_leftmost].up = total_nodes[column_index].up;
255     total_nodes[total_nodes[column_index].up].down = current_leftmost;
256     total_nodes[column_index].up = current_leftmost;
257     mutual_index[column_index].cul_value++;
258 }
259 void print_result()//打印出结果
260 {
261     int i, j, k, current_index;
262     int m, n;
263     int output[9][9];
264     for (i = 0; i < 9; i++)
265     {
266         for (j = 0; j < 9; j++)
267         {
268             output[i][j] = 0;
269         }
270     }
271     for (m = 0; m < stack_index; m++)
272     {
273         current_index = node_stack[m]-node_stack[m]%4;
274         k = total_nodes[current_index].column % 9;
275         i = (total_nodes[current_index].column-total_nodes[current_index].column % 9)/9;
276         current_index ++;
277         j = (total_nodes[current_index].column - total_nodes[current_index].column % 9-81) / 9;
278         output[i][j] = k + 1;
279     }
280     printf("***********************\n");
281     for (m = 0; m < 9; m++)
282     {
283         for (n = 0; n < 9; n++)
284         {
285             printf("%d ", output[m][n]);
286         }
287         printf("\n");
288     }
289 }
290
291 void creat_dlx_sudoku()//利用矩阵来建立十字网格
292 {
293     int i, j, k;
294     int row_position[9][9];//这个是行
295     int column_position[9][9];//这个是列
296     int small_position[9][9];//这个是每一个小方格
297     initial();
298     for (i = 0; i < 9; i++)
299     {
300         for (j = 0; j < 9; j++)
301         {
302             row_position[i][j] = 1;
303             column_position[i][j] = 1;
304             small_position[i][j] = 1;
305         }
306
307     }
308     for (i = 0; i < 9; i++)
309     {
310         for (j = 0; j < 9; j++)
311         {
312             if (out[i][j] != 0)
313             {
314                 row_position[i][out[i][j]-1] = 0;
315                 column_position[j][out[i][j]-1] = 0;
316                 small_position[(i / 3) * 3 + j / 3][out[i][j]-1] = 0;
317             }
318         }
319     }
320     for (i = 0; i < 9; i++)
321     {
322         for (j = 0; j < 9; j++)
323         {
324             if (out[i][j] != 0)
325             {
326                 insert_row(i, j, out[i][j]);
327             }
328             else
329             {
330                 for (k = 0; k < 9; k++)
331                 {
332                     if ((row_position[i][k] * column_position[j][k] * small_position[(i / 3) * 3 + j / 3][k])==1)
333                     {
334                         insert_row(i, j, k + 1);
335                     }
336                     else
337                     {
338                         //do nothing
339                     }
340                 }
341             }
342         }
343     }
344     heap_initial();
345 }
346 void in_stack(int target_to_stack)
347 {
348     int leftmost = target_to_stack - target_to_stack % 4;
349     for (int i = 0; i < 4; i++)//对于当前行的每一列
350     {
351         int current_column_traversal = leftmost + i;
352         current_column_traversal = total_nodes[current_column_traversal].down;
353         while (current_column_traversal != leftmost + i)//删除当前列相交的行
354         {
355             if (current_column_traversal != total_nodes[current_column_traversal].column)//即不是头行
356             {
357                 int temp_node = current_column_traversal - current_column_traversal % 4-1;
358                 for (int j = 0; j < 4; j++)
359                 {
360                     temp_node++;
361                     if (temp_node != current_column_traversal)
362                     {
363                         total_nodes[total_nodes[temp_node].down].up = total_nodes[temp_node].up;
364                         total_nodes[total_nodes[temp_node].up].down = total_nodes[temp_node].down;
365                     }
366                 }
367                 node_heap_decrease(temp_node);
368             }
369             current_column_traversal = total_nodes[current_column_traversal].down;
370         }
371     }
372     node_heap_decrease(target_to_stack);//最后对当前行进行删除
373     node_stack[stack_index++] = target_to_stack;//然后才是入栈
374     available_column -= 4;
375     //print_result();
376 }
377 void out_stack()//注意出栈的时候是相反的操作,所有删除都相反
378 {
379     int target_to_stack = node_stack[--stack_index];
380     int rightmost = target_to_stack - target_to_stack % 4+3;
381     for (int i = 0; i < 4; i++)//对于当前行的每一列
382     {
383         int current_column_traversal = rightmost - i;
384         current_column_traversal = total_nodes[current_column_traversal].up;
385         while (current_column_traversal != rightmost - i)//删除当前列相交的行
386         {
387             if (current_column_traversal != total_nodes[current_column_traversal].column)//即不是头行
388             {
389                 int temp_node = current_column_traversal - current_column_traversal % 4+4;
390                 for (int j = 0; j < 4; j++)
391                 {
392                     temp_node --;
393                     if (temp_node != current_column_traversal)
394                     {
395                         total_nodes[total_nodes[temp_node].down].up = temp_node;
396                         total_nodes[total_nodes[temp_node].up].down = temp_node;
397                     }
398                 }
399                 node_heap_increase(temp_node);
400             }
401             current_column_traversal = total_nodes[current_column_traversal].up;
402         }
403     }
404     node_heap_increase(target_to_stack);//最后对当前行进行回复
405     available_column += 4;
406     //print_result();
407 }
408 int find_next()//用来找下一个可以入栈的元素,如果无法入栈或者已经找到了解,则返回并进行回溯操作
409 {
410     int target_position;
411     int temp_node_one;
412     if (available_column == current_heap_number)
413     {
414         if (available_column == -1)
415         {
416             //print_result();
417             return 2;
418         }
419         else
420         {
421             target_position = mutual_index[0].position_index;
422             temp_node_one = total_nodes[target_position].down;
423             in_stack(temp_node_one);
424             return 1;
425         }
426     }
427     else
428     {
429         return 0;
430     }
431 }
432 void seek_sudoku()
433 {
434     int find_result = 0;
435     int temp_node_one;
436     while (1)
437     {
438         find_result = find_next();
439         if (!find_result)//如果无法入栈且目前没有找到解,则出栈
440         {
441             temp_node_one = node_stack[stack_index - 1];
442             out_stack();
443             temp_node_one = total_nodes[temp_node_one].down;
444             while ((temp_node_one==total_nodes[temp_node_one].column))//如果当前元素是当前列头节点,则递归出栈
445             {
446                 if (stack_index == 0)//如果栈空,则所有的搜索空间已经搜索完全 返回
447                 {
448                     return;
449                 }
450                 else
451                 {
452                     temp_node_one = node_stack[stack_index - 1];
453                     out_stack();
454                     temp_node_one = total_nodes[temp_node_one].down;
455                 }
456             }
457             in_stack(temp_node_one);//将所选元素入栈
458         }
459         else
460         {
461             if (find_result / 2)//如果已经找到结果,则返回,事实上我们可以更改这个逻辑来应对有多个解的情况,并把它全部打印
462             {
463                 return;
464             }
465         }
466     }
467 }
468 int main()
469 {
470     clock_t clock_one, clock_two, clock_three;
471     ifstream suduko_file("sudoku.txt");
472     char temp[82];
473     clock_one = clock();
474     int line = 1;
475     while (line!=49152)
476     {
477         suduko_file.getline(temp, 82);
478         for (int i = 0; i < 9; i++)
479         {
480             for (int j = 0; j < 9; j++)
481             {
482                 out[i][j] = temp[i * 9 + j] - ‘0‘;
483             }
484         }
485         creat_dlx_sudoku();
486         seek_sudoku();
487         line++;
488     }
489     clock_three = clock();
490     printf("%d mscond passed in seek_sudoku\n", clock_three - clock_one);
491 }
时间: 2024-11-05 17:24:51

跳舞链解数独 静态数组优化的相关文章

解数独算法的实现——剪枝优化

最近人工智能做个小实验,组队选了个数独游戏,顺便研究了一下.解数独感觉主流思想也就是深搜回溯了吧,优化就是各种剪枝方法. 1 引言 数独起源于18世纪初瑞士数学家欧拉等人研究的拉丁方阵(Latin Square),曾风靡日本和英国.现有解法包括基础解法:摒除法,余数法,进阶解法:区块摒除法(Locked Candidates).数组法(Subset).四角对角线(X-Wing).唯一矩形(Unique Rectangle).全双值坟墓(Bivalue Universal Grave).单数链(X

hiho一下 第四十七周 拓扑排序一 【静态数组链式前向星存储结构实现 + 拓扑跳出 】

题目1 : 拓扑排序·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 由于今天上课的老师讲的特别无聊,小Hi和小Ho偷偷地聊了起来. 小Ho:小Hi,你这学期有选什么课么? 小Hi:挺多的,比如XXX1,XXX2还有XXX3.本来想选YYY2的,但是好像没有先选过YYY1,不能选YYY2. 小Ho:先修课程真是个麻烦的东西呢. 小Hi:没错呢.好多课程都有先修课程,每次选课之前都得先查查有没有先修.教务公布的先修课程记录都是好多年前的,不但有重复的信息,好像很多

使用双向十字链表(或Dancing Links)解数独游戏

#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; struct Data { void assign(int x,int y,int z) { row=x; col=y; val=z; } int row,col,val; } data[730]; struct Node { Node(int x=0,int y=0): row(x),col(y),up(this)

【原创】一个基于简单剪枝的DFS解数独程序

问题来源:leetCode Sudoku Solver Write a program to solve aSudoku puzzle by filling the empty cells. Empty cells are indicated by the character *.*. You may assume that there will be only one unique solution. 问题链接: https://oj.leetcode.com/problems/sudoku-

HihoCoder1317 跳舞链

跳舞链 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho最近遇到一个难题,他需要破解一个棋局. 棋局分成了n行,m列,每行有若干个棋子.小Ho需要从中选择若干行使得每一列有且恰好只有一个棋子. 比如下面这样局面: 其中1表示放置有棋子的格子,0表示没有放置棋子. 对于上面这个问题,小Ho经过多次尝试以后得到了解为选择2.3.4行就可以做到. 但是小Ho觉得自己的方法不是太好,于是他求助于小Hi. 小Hi:小Ho你是怎么做的呢? 小Ho:我想每一行都只有两种状态

解数独(Python)

0.目录 1.介绍 2.一些通用函数 3.全局变量(宏变量) 4.数独预处理(约束传播) 5.解数独(深度优先搜索+最小代价优先) 6.主函数 7.总代码 1.介绍 数独是一个非常有趣味性的智力游戏,数独起源于18世纪初瑞士数学家欧拉等人研究的拉丁方阵(Latin Square). 参与者需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个宫内的数字均含1-9,不重复. 一个数独谜题是由81个方块组成的网格.大部分爱好者把列标为1-9,把行标为A-I,把9个方块

解数独——命令行程序的实现

Github项目地址 地址 PSP表格 PSP2.1 Personal Software Process Stages 预估耗时(min) 实际耗时(min) Planning 计划 30 15 Estimate 估计这个任务需要多少时间 48*60 12*60 Development 开发 20*60 10*60 Analysis 需求分析 (包括学习新技术) 2*60 5*60 Design Spec 生成设计文档 20 15 Design Review 设计复审 10 10 Coding

中大型网站静态资源优化及存储

静态资源优化: 合并 减少http请求有这样几个优点: (1) 减少DNS请求所耗费的时间 (2) 减少服务器压力(CPU,IO) (3) 减少http请求头(当我们对服务器发起一个请求的时候,我们会携带着这个域名下的cookie和一些其他的信息在http头部里,然后服务器响应请求的时候也会带回一些cookie之类的头部信息.这些信息有的时候会很大,在这种请求和响应的时候会影响带宽性能) 合并请求: lvmama首页 <link rel="stylesheet" href=&qu

MySQL配置文件mysql.ini参数详解、MySQL性能优化

MySQL配置文件mysql.ini参数详解.MySQL性能优化 my.ini(Linux系统下是my.cnf),当mysql服务器启动时它会读取这个文件,设置相关的运行环境参数. my.ini分为两块:Client Section和Server Section.   Client Section用来配置MySQL客户端参数.   要查看配置参数可以用下面的命令: show variables like '%innodb%'; # 查看innodb相关配置参数 show status like