Fork me on GitHub

数据结构与算法——五个常规算法之三 · 回溯算法

回溯的基本原理

在问题的解空间中,按深度优先遍历策略,从根节点出发搜索解空间树。算法搜索至解空间 的任意一个节点时,先判断该节点是否包含问题的解。如果确定不包含,跳过对以该节点为根的 子树的搜索,逐层向其祖先节点回溯,否则进入该子树,继续深度优先搜索。

 

回溯法解问题的所有解时,必须回溯到根节点,且根节点的所有子树都被搜索后才结束。回 溯法解问题的一个解时,只要搜索到问题的一个解就可结束。

 

回溯的基本步骤

1. 定义问题的解空间

2. 确定易于搜索的解空间结构

3. 以深度优先搜索的策略搜索解空间,并在搜索过程中尽可能避免无效搜索

 

某企业面试题:

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以 从矩阵中任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了 矩阵的某一格,那么该路径不能再次进入该格子。例如在下面的 3×4 的矩阵中包含一条字符串 “bfce”的路径(路径中的字母用下划线标出)。但矩阵中不包含字符串“abfb”的路径,因为 字符串的第一个字符 b 占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。

A B T G
C F C S
J D E H

 

 

 

 

 

解题思路:

首先,在矩阵中任选一个格子作为路径的起点。如果路径上的第 i 个字符不是待搜索的目标字 符 ch,那么这个格子不可能处在路径上的第 i 个位置。如果路径上的第 i 个字符正好是 ch,那么 往相邻的格子寻找路径上的第 i+1 个字符。除在矩阵边界上的格子之外,其他格子都有 4 个相邻 的格子。重复这个过程直到路径上的所有字符都在矩阵中找到相应的位置。 由于路径不能重复进入矩阵的格子,还需要定义和字符矩阵大小一样的布尔值矩阵,用来标识 路径是否已经进入每个格子。 当矩阵中坐标为(row, col)的格子和路径字符串中相应的字符一 样时,从 4 个相邻的格子(row,col-1),(row-1,col),(row,col+1)以及(row+1,col)中去定位路径字符串中 下一个字符, 如果 4 个相邻的格子都没有匹配字符串中下一个的字符,表明当前路径字符串中字 符在矩阵中的定位不正确,我们需要回到前一个,然后重新定位。

 

源码实现:

  1 #include <stdio.h>
  2 #include <string>
  3 
  4 using namespace std;
  5 
  6 bool hasPathCore(const char* matrix, int rows, int cols, int row, int col,
  7                  const char* str, int& pathLength, bool* visited);
  8 /*****************************************
  9 功能: 查找矩阵中是否含有 str 指定的字串
 10 参数说明:
 11 matrix 输入矩阵
 12 rows 矩阵行数
 13 cols 矩阵列数
 14 str 要搜索的字符串
 15 返回值: 是否找到 true 是,false 否
 16 *******************************************/
 17 
 18 bool hasPath(const char* matrix, int rows, int cols, const char* str)
 19 {
 20     if(matrix == nullptr || rows < 1 || cols < 1 || str == nullptr)
 21     return false;
 22 
 23     bool *visited = new bool[rows * cols];
 24     memset(visited, 0, rows * cols);
 25     int pathLength = 0;
 26     
 27     //遍历矩阵中每个点,做为起点开始进行搜索
 28     for(int row = 0; row < rows; ++row)
 29     {
 30         for(int col = 0; col < cols; ++col)
 31         {
 32             if(hasPathCore(matrix, rows, cols, row, col, str, pathLength, visited))
 33             {
 34                 return true;
 35             }
 36         }
 37     }
 38     delete[] visited;
 39     return false;
 40 }
 41 
 42 /*探测下一个字符是否存在*/
 43 bool hasPathCore(const char* matrix, int rows, int cols, int row,
 44 int col, const char* str, int& pathLength, bool* visited)
 45 {
 46     if(str[pathLength] == '\0')
 47     return true;
 48     bool hasPath = false;
 49     if(row >= 0 && row < rows && col >= 0 && col < cols
 50     && matrix[row * cols + col] == str[pathLength]
 51     && !visited[row * cols + col])
 52     {
 53         ++pathLength;
 54         visited[row * cols + col] = true;
 55         hasPath = hasPathCore(matrix, rows, cols, row, col - 1,    str, pathLength, visited)
 56         || hasPathCore(matrix, rows, cols, row - 1, col, str, pathLength, visited)
 57         || hasPathCore(matrix, rows, cols, row, col + 1, str, pathLength, visited)
 58         || hasPathCore(matrix, rows, cols, row + 1, col, str, pathLength, visited);
 59         if(!hasPath)
 60         {
 61             --pathLength;
 62             visited[row * cols + col] = false;
 63         }
 64     }
 65     return hasPath;
 66 }
 67 
 68 
 69 /*单元测试代码*/
 70 void Test(const char* testName, const char* matrix, int rows, int cols,
 71 const char* str, bool expected)
 72 {
 73     if(testName != nullptr)
 74     printf("%s begins: ", testName);
 75     if(hasPath(matrix, rows, cols, str) == expected)
 76     printf("Passed.\n");
 77     else
 78     printf("FAILED.\n");
 79 }
 80 
 81 //ABTG
 82 //CFCS
 83 //JDEH
 84 //BFCE
 85 void Test1()
 86 {
 87     const char* matrix = "ABTGCFCSJDEH";
 88     const char* str = "BFCE";
 89     Test("功能测试 1", (const char*) matrix, 3, 4, str, true);
 90 }
 91 
 92 //ABCE
 93 //SFCS
 94 //ADEE
 95 //SEE
 96 void Test2()
 97 {
 98     const char* matrix = "ABCESFCSADEE";
 99     const char* str = "SEE";
100     Test("功能测试 2", (const char*) matrix, 3, 4, str, true);
101 }
102 
103 //ABTG
104 //CFCS
105 //JDEH
106 //ABFB
107 void Test3()
108 {
109     const char* matrix = "ABTGCFCSJDEH";
110     const char* str = "ABFB";
111     Test("功能测试 3", (const char*) matrix, 3, 4, str, false);
112 }
113 
114 //ABCEHJIG
115 //SFCSLOPQ
116 //ADEEMNOE
117 //ADIDEJFM
118 //VCEIFGGS
119 //SLHECCEIDEJFGGFIE
120 void Test4()
121 {
122     const char* matrix = "ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS";
123     const char* str = "SLHECCEIDEJFGGFIE";
124     Test("功能测试 4", (const char*) matrix, 5, 8, str, true);
125 }
126 
127 //ABCEHJIG
128 //SFCSLOPQ
129 //ADEEMNOE
130 //ADIDEJFM
131 //VCEIFGGS
132 //SGGFIECVAASABCEHJIGQEM
133 void Test5()
134 {
135     const char* matrix = "ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS";
136     const char* str = "SGGFIECVAASABCEHJIGQEM";
137     Test("功能测试 5", (const char*) matrix, 5, 8, str, true);
138 }
139 
140 //ABCEHJIG
141 //SFCSLOPQ
142 //ADEEMNOE
143 //ADIDEJFM
144 //VCEIFGGS
145 //SGGFIECVAASABCEEJIGOEM
146 void Test6()
147 {
148     const char* matrix = "ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS";
149     const char* str = "SGGFIECVAASABCEEJIGOEM";
150     Test("功能测试 6", (const char*) matrix, 5, 8, str, false);
151 }
152 
153 //ABCEHJIG
154 //SFCSLOPQ
155 //ADEEMNOE
156 //ADIDEJFM
157 //VCEIFGGS
158 //SGGFIECVAASABCEHJIGQEMS
159 void Test7()
160 {
161     const char* matrix = "ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS";
162     const char* str = "SGGFIECVAASABCEHJIGQEMS";
163     Test("功能测试 7", (const char*) matrix, 5, 8, str, false);
164 }
165 
166 //AAAA
167 //AAAA
168 //AAAA
169 //AAAAAAAAAAAA
170 void Test8()
171 {
172     const char* matrix = "AAAAAAAAAAAA";
173     const char* str = "AAAAAAAAAAAA";
174     Test("边界值测试 8", (const char*) matrix, 3, 4, str, true);
175 }
176 
177 //AAAA
178 //AAAA
179 //AAAA
180 //AAAAAAAAAAAAA
181 void Test9()
182 {
183     const char* matrix = "AAAAAAAAAAAA";
184     const char* str = "AAAAAAAAAAAAA";
185     Test("边界值测试 9", (const char*) matrix, 3, 4, str, false);
186 }
187 
188 //A
189 //A
190 void Test10()
191 {
192     const char* matrix = "A";
193     const char* str = "A";
194     Test("边界值测试 10", (const char*) matrix, 1, 1, str, true);
195 }
196 
197 //A
198 //B
199 void Test11()
200 {
201     const char* matrix = "A";
202     const char* str = "B";
203     Test("边界值测试 11", (const char*) matrix, 1, 1, str, false);
204 }
205 
206 void Test12()
207 {
208     Test("特殊情况测试 12", nullptr, 0, 0, nullptr, false);
209 }
210 
211 int main(int argc, char* argv[])
212 {
213     Test1();
214     Test2();
215     Test3();
216     Test4();
217     Test5();
218     Test6();
219     Test7();
220     Test8();
221     Test9();
222     Test10();
223     Test11();
224     Test12();
225     system("pause");
226     return 0;
227 }

 

 

 

 

 

 

==========================================================================================================================

 

posted @ 2020-12-10 21:59  索智源  阅读(163)  评论(0编辑  收藏  举报