搜索算法
搜索算法有很多種類型,一般來說就是深度優先搜索,廣度優先搜索,A*搜索,IDA*搜索這四種類型的搜索,而本篇講述的就是其中最核心,最簡單的搜索深度優先搜索和廣度優先搜索。
DFS算法簡述
深度優先搜索是一種適用於樹形結構的搜索,它和數據結構棧緊密相連。對於這種算法而言,它的主要步驟大致如下:
- 找到當前可以拓展的點,那么立即走入這個分支點。
- 如果當前搜索分支,無效或者已經找到目標,那么退回到上一步,即回溯。
- 每一個點最多會被訪問兩次。訪問含義是入棧一次,出棧一次。
DFS性質
DFS序列就是深度優先搜索最為重要的性質,它可以將一個子樹變成一個區間。
代碼實現(遞歸)
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_N 10000 typedef struct Node { int vertex; struct Node *next; } Node, *LinkedList; LinkedList insert_node(LinkedList head, int index) { Node *node = (Node *)malloc(sizeof(Node)); node->vertex = index; node->next = head; head = node; return head; } typedef struct Graph { LinkedList edges[MAX_N]; int n; int visited[MAX_N]; } Graph; void init(Graph * g, int n) { g->n = n; for (int i = 0; i < g->n; ++i) { g->edges[i] = NULL; } } void insert(Graph *g, int x, int y) { if (x < 0 || x >= g->n || y < 0 || y >= g->n) { return ; } g->edges[x] = insert_node(g->edges[x], y); g->edges[y] = insert_node(g->edges[y], x); } void clear(Graph *g) { for (int i = 0; i < g->n; ++i) { Node *head = g->edges[i]; while (head != NULL) { Node *delete_node = head; head = head->next; free(delete_node); } } free(g); } void dfs(Graph *g, int index) { printf("%d\n", index); g->visited[index] = 1; for (Node *tmp = g->edges[index]; tmp != NULL; tmp = tmp->next) { if (!g->visited[tmp->vertex]) { dfs(g, tmp->vertex); } } return; } int main() { int n, m, k; scanf("%d %d", &n, &m); Graph *graph = (Graph *)malloc(sizeof(Graph)); init(graph, n); for (int i = 0; i < m; ++i) { int x, y; scanf("%d %d", &x, &y); insert(graph, x, y); } scanf("%d", &k); dfs(graph, k); clear(graph); return 0; }
算法例題
BFS算法簡述
廣度優先搜索和深度優先搜索恰恰相反,它是一種適用於圖型結構的搜索,它和數據結構隊列緊密向量。對於這種算法而言,它主要的步驟大致如下所示:
- 找到當前可以拓展的點,將它放入候選隊列之中。
- 每次選取候選隊列的隊頭,作為當前狀態。
BFS性質
對於廣度優先搜索而言,它是一種逐層遍歷的算法,所有狀態按照入隊的先后順序具有層次單調性,也就是所謂的步數單調性質,如果每一次拓展恰好對應一部,那么當第一個狀態第一次被訪問(入隊),就會得到從起始狀態到達該狀態的最少步數。
代碼實現(隊列)
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_N 10000 typedef struct Queue { int *data; int head, tail, length; } Queue; void init_queue(Queue *q, int length_input) { q->data = (int *)malloc(sizeof(int) * length_input); q->length = length_input; q->head = 0; q->tail = -1; } void push(Queue *q, int element) { if (q->tail + 1 < q->length) { q->tail++; q->data[q->tail] = element; } } int front(Queue *q) { return q->data[q->head]; } void pop(Queue *q) { q->head++; } int empty(Queue *q) { if (q->head > q->tail) { return 1; } else { return 0; } } void clear_queue(Queue *q) { free(q->data); free(q); } typedef struct Node { int vertex; struct Node *next; }Node, *LinkedList; LinkedList insert_node(LinkedList head, int index) { Node *node = (Node *)malloc(sizeof(Node)); node->vertex = index; node->next = head; head = node; return head; } typedef struct Graph { LinkedList edges[MAX_N]; int visited[MAX_N]; int n; }Graph; void init_graph(Graph *g, int n) { g->n = n; memset(g->visited, 0, sizeof(g->visited)); for (int i = 0; i < g->n; ++i) { g->edges[i] = NULL; } } void insert(Graph *g, int x, int y) { if (x < 0 || x >= g->n || y < 0 || y >= g->n) { return ; } g->edges[x] = insert_node(g->edges[x], y); g->edges[y] = insert_node(g->edges[y], x); } void clear_graph(Graph *g) { for (int i = 0; i < g->n; ++i) { Node *head = g->edges[i]; while (head != NULL) { Node *delete_node = head; head = head->next; free(delete_node); } } free(g); } void bfs(Graph *g, int id) { Queue *queue = (Queue *)malloc(sizeof(Queue)); init_queue(queue, g->n); printf("%d\n", id); g->visited[id] = 1; push(queue, id); while (!empty(queue)) { int tmp = front(queue); pop(queue); for (Node *adj = g->edges[tmp]; adj != NULL; adj = adj->next) { if (!g->visited[adj->vertex]) { printf("%d\n", adj->vertex); push(queue, adj->vertex); g->visited[adj->vertex] = 1; } } } clear_queue(queue); } int main() { int n, m, k; scanf("%d %d", &n, &m); Graph *graph = (Graph *)malloc(sizeof(Graph)); init_graph(graph, n); for (int i = 0; i < m; ++i) { int x, y; scanf("%d %d", &x, &y); insert(graph, x, y); } scanf("%d", &k); bfs(graph, k); clear_graph(graph); return 0; }
算法例題
參考資料:
https://www.acwing.com/blog/content/173/
https://www.acwing.com/blog/content/173/