相信很多同學都聽過深度優先搜索的大名,這是一種基于遞歸的搜索方法。記得自己第一次學習深度優先搜索的時候想了半天也沒有搞明白實現原理,總是感覺理解的很不到位。最后為了應付考試不得不將偽代碼死記硬背下來。在這里,我想通過這篇文章簡單的介紹一下這種經常被用到的搜索方法。
1,有趣的卡片
相信很多同學在高中階段都見過這樣的數學題:手中有3張卡片和三個盒子,那么有多少種方法讓每個盒子里有且只有一張卡片。對于這樣的題目大家的第一反應這就是一個簡單的全排列。那么,我們應該如何用代碼去實現這個全排列呢?
(1), 確定當前盒子應放的卡片
要想將卡片放入當前的盒子里,首先要滿足兩個條件。第一,當前的盒子里沒有卡片。第二,將要放入當前盒子的卡片是沒有用過的。
因此我們可以建立當前盒子放入卡片的偽代碼:
int book[10];//用來標記已經使用過的卡片
int boxes[10];//用來儲存卡片的盒子
int step;//用來標記盒子的號碼
//測試每一張卡片能否放入盒子中
- (void) dfs {
for (int i = 0; i < book.size();i ++) {
//測試當前卡片是否用過
if(book[i]==0){
//標記用過的卡片
book[i] = 1;
//將卡片放入盒子中
boxes[step] = i;
}
}
}
(2),確定下一個盒子應該放入的卡片
這時候我們就要使用遞歸的思想了,因為每一個盒子放入的卡片判定條件都是相同的。因此我們可以用遞歸的方式去判定下一個盒子是否能放入卡片。偽代碼如下:
int book[10];//用來標記已經使用過的卡片
int boxes[10];//用來儲存卡片的盒子
int step;//用來標記盒子的號碼
//測試每一張卡片能否放入盒子中
- (void) dfs: (int) step {
for (int i = 0; i < book.size();i ++) {
//測試當前卡片是否用過
if(book[i]==0){
//標記用過的卡片
book[i] = 1;
//將卡片放入盒子中
boxes[step] = i;
//使用遞歸將卡片放入下一個盒子
dfs(step+1);
//一定要將已經放入的卡片拿出來
book[i] = 0;
}
}
}
2, Objective-C代碼實現
- (instancetype) initWithNumbers:(NSInteger)numbers {
self = [super init];
if (self) {
_numbers = numbers;
_book = [NSMutableArray arrayWithCapacity:numbers];
for (NSInteger i = 0; i < self.numbers; i++) {
_book[i] = [NSNumber numberWithInteger:0];
}
_boxs = [NSMutableArray arrayWithCapacity:self.numbers];
}
return self;
}
- (void) depthFirstSearching:(NSInteger) steps {
if (steps == self.numbers) {
for (NSInteger i = 0; i < self.numbers; i++) {
NSLog(@"%.0f",[self.boxs[i] floatValue]);
}
NSLog(@"http://////////////////");
return;
}
for (NSInteger i = 0; i < self.numbers; i ++) {
if ([self.book[i] integerValue] == 0) {
self.book[i] = [NSNumber numberWithInteger:1];
self.boxs[steps] = [NSNumber numberWithInteger:i];
[self depthFirstSearching:steps+1];
self.book[i] = [NSNumber numberWithInteger:0];
}
}
}