一、 開發環境
l Windows10 版本號1903
l RAM 16GB 3200MHz 三星
l AMD Ryzen 7 2700X 3.90GHz
l SSD 三星 MZVLB1TOHALR-00000
二、 文件讀入
在進行測試的過程中發現1e6的數據讀入大概需要300秒,遠遠高於寫入的6秒鐘。顯然由於硬盤限制寫入時間應該大於讀入,因此文件讀入代碼必然是有問題的,時間是不可接受的。
原文件讀入的代碼如下:
- inline void mallocSudoku(Sudoku& s)
- {
- if (s == nullptr)
- {
- s = new int* [10];
- for (int i = 0; i < 10; i++)
- {
- s[i] = new int[10];
- }
- 10. }
11. }
- 12.
13. inline void freeSudoku(Sudoku& s)
14. {
- 15. if (s != nullptr)
- 16. {
- 17. for (int i = 0; i < 10; i++)
- 18. {
- 19. delete[] s[i];
- 20. }
- 21. delete[] s;
- 22. s = nullptr;
- 23. }
24. }
- 25.
26. inline void readLineFromFile(char* line)
27. {
- 28. char* tmp = new char;
- 29. DWORD num_bytes_read = 0;
- 30. for (int i = 0; i < 9; i++)//依據約定,一行最多有9個數字
- 31. {
- 32. *tmp = 0;
- 33. while (*tmp < '0' || *tmp > '9')
- 34. {
- 35. if (ReadFile(h_sudoku_problem_txt, tmp, 1, &num_bytes_read, NULL) && num_bytes_read == 0)
- 36. {
- 37. is_end = true;
- 38. return;
- 39. }
- 40. //num_bytes_read++;
- 41. }
- 42. line[i] = *tmp;
- 43. }
- 44. delete tmp;
45. }
- 46.
47. inline bool getSudokuFromFile(Sudoku s)
48. {
- 49. char* line = new char[9];
- 50. for (int i = 0; i < 9; i++)
- 51. {
- 52. readLineFromFile(line);
- 53. if (is_end)
- 54. return false;
- 55. for (int j = 0; j < 9; j++)
- 56. s[i + 1][j + 1] = line[j] - '0';
- 57. }
- 58.
- 59. delete[] line;
- 60. return true;
61. }
- 62.
63. //一次性讀入一千個數獨
64. inline void readSudoku()
65. {
- 66. for (int i = 0; i < BUFF_SIZE; i++)
- 67. {
- 68. Sudoku tmp = nullptr;
- 69. mallocSudoku(tmp);
- 70. if (getSudokuFromFile(tmp) == false)
- 71. {
- 72. freeSudoku(tmp);
- 73. return;
- 74. }
- 75. buff.push_back(tmp);
- 76. }
- 77. return;
- }
分析代碼,不難發現問題所在,那就是調用一次ReadFile只讀入了一個字節的數據。原代碼主要是考慮到可能的數獨文件格式問題,通過再次閱讀問題要求,發現數獨問題文件格式是固定的,因此可一次讀入163個字節(與輸出一致)。由於最後一個數獨的後面沒有空行,因此讀入的數據是162個字節,由此可以作爲結束判斷。另外一方面,可以一次性讀入多個數獨進行分析。若讀入字節數小於163的整數倍,則已讀完。經過一系列測試,代碼修改如下:
- inline void toSudoku(char* tmp, DWORD& n_bytes_read)
- {
- //由於讀取時的限制,num_of_sudoku_in_buff <= BUFF_SIZE
- num_of_sudoku_in_buff = n_bytes_read / num_bytes_of_sudoku_infile;
- if (is_end)//因爲結束時,向下取整,少了一個
- {
- num_of_sudoku_in_buff++;
- }
- for (int i = 0, j = 0; i < num_of_sudoku_in_buff; i++, j++)
- 10. {
- 11. Sudoku s = buff[i];
- 12. for (int row_idx = 1, col_idx = 1; j < (i + 1) * num_bytes_of_sudoku_infile - 1; j++, j++)
- 13. {
- 14. s[row_idx][col_idx++] = tmp[j] - '0';
- 15. if (col_idx == 10)
- 16. {
- 17. row_idx++;
- 18. col_idx = 1;
- 19. }
- 20. }
- 21. }
22. }
- 23.
24. //一次性讀入一千個數獨
25. inline void readSudoku()
26. {
- 27. char* tmp = new char[num_bytes_of_sudoku_infile * BUFF_SIZE + 10];
- 28. ReadFile(h_sudoku_problem_txt, tmp, num_bytes_of_sudoku_infile * BUFF_SIZE, &n_bytes_read, NULL);
- 29. if (num_bytes_of_sudoku_infile * BUFF_SIZE > n_bytes_read)
- 30. is_end = true;
- 31. toSudoku(tmp, n_bytes_read);
- 32. return;
- }
同時在文件讀入修改中,將原先的vector更改爲了數組形式,通過提前申請空間的方式減少了在獲取數獨和求解數獨後釋放數獨空間的時間。
在只更改文件讀入方式的情況下,時間從300秒降到了11秒,在將vector更改爲數獨數組之後,減少了new 和 delete的時間,又降低到了8秒鐘。