1. 程式人生 > 實用技巧 >資料結構與演算法——五個常規演算法之三 · 回溯演算法

資料結構與演算法——五個常規演算法之三 · 回溯演算法

回溯的基本原理

在問題的解空間中,按深度優先遍歷策略,從根節點出發搜尋解空間樹。演算法搜尋至解空間 的任意一個節點時,先判斷該節點是否包含問題的解。如果確定不包含,跳過對以該節點為根的 子樹的搜尋,逐層向其祖先節點回溯,否則進入該子樹,繼續深度優先搜尋。

回溯法解問題的所有解時,必須回溯到根節點,且根節點的所有子樹都被搜尋後才結束。回 溯法解問題的一個解時,只要搜尋到問題的一個解就可結束。

回溯的基本步驟

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 }

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