This commit is contained in:
2026-06-15 09:00:38 +08:00
parent fec66377d5
commit 4640c5e02b
191 changed files with 6046 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
#include <stdio.h>
// 归并函数
void merge(int arr[], int left, int middle,
int right, int temp[]) {
int i = left; // 左数组起始索引
int j = middle + 1; // 右数组起始索引
int k = left; // 合并后数组起始索引
// 将数据复制到临时数组
for (int m = left; m <= right; ++m)
temp[m] = arr[m];
// 合并临时数组到 arr[left..right]
while (i <= middle && j <= right) {
if (temp[i] <= temp[j])
arr[k++] = temp[i++];
else
arr[k++] = temp[j++];
}
// 拷贝剩余元素(如果有)
while (i <= middle)
arr[k++] = temp[i++];
}
// 归并排序函数
void mergeSort(int arr[], int left, int right, int temp[]) {
if (left < right) {
int middle = left + (right - left) / 2;
mergeSort(arr, left, middle, temp); // 排左半部分
mergeSort(arr, middle + 1, right, temp); // 排右半部分
merge(arr, left, middle, right, temp); // 合并两个已排部分
}
}
// 打印数组
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
int main() {
int arr[] = {8, 7, 6, 15, 4, 3, 2, 10};
int arrSize = sizeof(arr) / sizeof(arr[0]);
int temp[arrSize];
printf("原始数组: ");
printArray(arr, arrSize);
mergeSort(arr, 0, arrSize - 1, temp);
printf("排序后的数组: ");
printArray(arr, arrSize);
return 0;
}
Binary file not shown.
+69
View File
@@ -0,0 +1,69 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// 判断当前皇后放置是否合法
int place(int x[], int j, int n) {
if (x[j] == j )
return 0; // 禁用:位置在棋盘左上到右下对角线上
// 判断是否在同一列,或者是否在同一对角线上
for (int i = 1; i < j; i++) {
if (x[i] == x[j] || abs(j - i) == abs(x[j] - x[i]))
return 0; // 不合法
}
return 1; // 合法
}
// 非递归方式解 N 皇后问题
void nQNoRec(int x[], int n) {
int j = 1; // j 表示当前放置第 j 个皇后
for (int i = 1; i <= n; i++)
x[i] = 0;
while (j >= 1) {
while (x[j] < n) {
x[j] = x[j] + 1;
if (place(x, j, n)) {
j = j + 1;
if (j > n) { // 到达叶子节点
// 输出解
for (int i = 1; i <= n; i++)
printf("%d\t", x[i]);
printf("\n");
j = j - 1;
}
}
}
x[j] = 0; // 回溯时,恢复当前位置的状态
j = j - 1; // 向上回溯
}
}
// 递归方式解 N 皇后问题
void nQueenRec(int x[], int j, int n) {
if (j > n) { // 搜索到叶子节点
// 输出解
for (int i = 1; i <= n; i++)
printf("%d\t", x[i]);
printf("\n");
} else { // 尝试在第 j 行放置皇后
for (int i = 1; i <= n; i++) {
x[j] = i;
if (place(x, j, n))
nQueenRec(x, j + 1, n);
}
}
}
int main() {
int n = 6; // 皇后个数
int x[n + 1]; // 存储每行皇后的位置
printf("Recursive solution:\n");
nQueenRec(x, 1, n); // 递归方式解法
printf("****************************\n");
printf("Non-recursive solution:\n");
nQNoRec(x, n); // 非递归方式解法
return 0;
}
Binary file not shown.
+82
View File
@@ -0,0 +1,82 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MIN_DISTANCE 2
// 判断当前皇后放置是否合法,并且符合安全距离条件
int place(int x[], int j) {
for (int i = 1; i < j; i++) {
// 检查列冲突、对角线冲突以及最小安全距离
if (x[i] == x[j] || abs(j - i) == abs(x[j] - x[i]) ||
abs(x[j] - x[i]) < MIN_DISTANCE || abs(j - i) < MIN_DISTANCE) {
return 0; // 不合法
}
}
return 1; // 合法
}
// 非递归方式解 N 皇后问题
void nQNoRec(int x[], int n, int *foundSolution) {
int j = 1; // j 表示当前放置第 j 个皇后
for (int i = 1; i <= n; i++)
x[i] = 0;
while (j >= 1) {
while (x[j] < n) {
x[j] = x[j] + 1;
if (place(x, j)) {
j = j + 1;
if (j > n) { // 到达叶子节点
*foundSolution = 1;
return; // 找到一个解即可返回
}
}
}
x[j] = 0; // 回溯时,恢复当前位置的状态
j = j - 1; // 向上回溯
}
}
// 递归方式解 N 皇后问题
void nQueenRec(int x[], int j, int n, int *foundSolution) {
if (j > n) { // 搜索到叶子节点
*foundSolution = 1;
return; // 找到一个解即可返回
} else { // 尝试在第 j 行放置皇后
for (int i = 1; i <= n; i++) {
x[j] = i;
if (place(x, j))
nQueenRec(x, j + 1, n, foundSolution);
if (*foundSolution) return; // 如果已经找到解,则提前退出
}
}
}
int main() {
for (int n = 1; n <= 100; n++) {
int x[n + 1]; // 存储每行皇后的位置
int hasSolution = 0;
printf("Testing n = %d:\n", n);
// 使用非递归方式检查是否有解
nQNoRec(x, n, &hasSolution);
if (hasSolution) {
printf("There is at least one solution for n = %d.\n", n);
} else {
printf("No solution found for n = %d.\n", n);
}
// 也可以使用递归方式进行验证(可选)
// hasSolution = 0;
// nQueenRec(x, 1, n, &hasSolution);
// if (!hasSolution) {
// printf("No solution found for n = %d using recursive method.\n", n);
// }
printf("****************************\n");
}
return 0;
}
Binary file not shown.
+60
View File
@@ -0,0 +1,60 @@
#include <stdio.h>
#include <stdbool.h>
#define NUM_PLACES 4
void printPath(int *path) {
for (int i = 0; i < NUM_PLACES; ++i)
printf("%c", 'A' + path[i]); // 将数字转换为对应的字母(例如:0 -> 'A', 1 -> 'B' 等)
printf("\n");
}
// 回溯函数:尝试构建所有可能的路径组合
void backtrack(int *path, bool used[NUM_PLACES], int step) {
// 如果已经到达了最后一个步骤,则打印路径
if (step == NUM_PLACES) {
printPath(path); // 调用打印函数
return;
}
// 尝试每一个可能的下一个位置
for (int next = 0; next < NUM_PLACES; ++next) {
// 如果这个位置还没有被使用过
if (!used[next]) {
// 特殊情况处理:如果当前要放置的是 A (即 next == 0)
// 并且后面还有空间放置 B (即 step + 1 < NUM_PLACES)
// 同时 B 还没有被使用过 (!used[1])
if (next == 0 && step + 1 < NUM_PLACES && !used[1]) {
// 把 A 和 B 作为一对连续的位置放置
path[step] = 0; // 放置 A
path[step + 1] = 1; // 放置 B
used[0] = used[1] = true; // 标记 A 和 B 已经被使用
// 继续递归寻找后续的路径
backtrack(path, used, step + 2);
// 回溯:取消标记 A 和 B 的使用状态
used[0] = used[1] = false;
} else if (next != 0 && next != 1) { // 如果不是 A 或 B
// 只放置 C 或者 D,确保 A 总是紧跟着 B 出现
path[step] = next; // 放置 C 或 D
used[next] = true; // 标记当前位置已被使用
// 继续递归寻找后续的路径
backtrack(path, used, step + 1);
// 回溯:取消标记当前位置的使用状态
used[next] = false;
}
}
}
}
int main() {
int path[NUM_PLACES]; // 创建一个用来存储路径的数组
bool used[NUM_PLACES] = {false}; // 创建一个布尔数组来追踪哪些位置已经被使用
// 开始回溯,从一个空路径开始
backtrack(path, used, 0);
return 0;
}
Binary file not shown.
+39
View File
@@ -0,0 +1,39 @@
#include <stdio.h>
#include <stdbool.h>
#define NUM_PLACES 4
// 回溯函数:尝试构建所有可能的路径组合,A 总是紧跟 B
void backtrack(int *path, bool used[NUM_PLACES], int step)
{
if (step >= NUM_PLACES)
{ // 边界条件:当步骤数等于地点数时打印路径
for (int i = 0; i < NUM_PLACES; ++i)
printf("%c", 'A' + path[i]);
printf("\n");
return;
}
// 如果还有足够的空间,尝试放置 A 和 B 作为一对
if (step + 1 < NUM_PLACES && !used[0] && !used[1]) {
path[step] = 0; // 放置 A
path[step + 1] = 1; // 放置 B
used[0] = used[1] = true;
backtrack(path, used, step + 2);
used[0] = used[1] = false;
}
// 尝试放置 C 或 D
for (int i = 2; i < NUM_PLACES; ++i) {
if (!used[i]) {
path[step] = i;
used[i] = true;
backtrack(path, used, step + 1);
used[i] = false;
}
}
}
int main(){
int path[NUM_PLACES];
bool used[NUM_PLACES] = {false};
// 开始回溯,从一个空路径开始
backtrack(path, used, 0);
return 0;
}
Binary file not shown.
+47
View File
@@ -0,0 +1,47 @@
#include <stdio.h>
#include <stdbool.h>
#define NUM_PLACES 4
// 函数:打印路径,将索引转换为1到4的数字表示
void printPath(int *path) {
for (int i = 0; i < NUM_PLACES; ++i) {
printf("%d ", path[i] + 1); // 将索引转换为1-based索引(即0变为1, 1变为2等)
}
printf("\n"); // 打印完路径后换行
}
// 回溯函数:生成所有符合条件的路径
void backtrack(int *path, bool used[NUM_PLACES], int step) {
if (step == NUM_PLACES) { // 如果已经选择了所有的地点
printPath(path); // 打印当前路径
return;
}
for (int next = 0; next < NUM_PLACES; ++next) { // 尝试选择下一个地点
if (!used[next]) { // 如果该地点还没有被访问过
if (next == 0 && step + 1 < NUM_PLACES && !used[1]) {
// 如果当前要放置的是地点1,并且后面还有空间且地点2未被使用,
// 则将地点1和地点2作为一个单元放置在一起
path[step] = 0; // 放置地点1
path[step + 1] = 1; // 紧接着放置地点2
used[0] = used[1] = true; // 标记地点1和地点2为已使用
backtrack(path, used, step + 2); // 递归尝试下一步
used[0] = used[1] = false; // 回溯,恢复状态
} else if (next != 0 && next != 1) {
// 如果当前不是选择地点1或地点2,则可以选择地点3或地点4
path[step] = next; // 放置地点3或地点4
used[next] = true; // 标记该地点为已使用
backtrack(path, used, step + 1); // 递归尝试下一步
used[next] = false; // 回溯,恢复状态
}
}
}
}
int main() {
int path[NUM_PLACES]; // 用于存储路径的数组
bool used[NUM_PLACES] = {false}; // 用于跟踪哪些地点已经被访问过
// 从一个空路径开始回溯
backtrack(path, used, 0);
return 0;
}
Binary file not shown.