C语言:矩阵中的路径

设计一个函数,判断在矩阵中是否存在一条包含某字符串所有字符的路径。路径可从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。

例如:对于以下矩阵

a b t f
c f c s
j d e h

该矩阵包含bfce路径,但不包含abfb路径。

这道题目是一道典型的回溯法题目。
首先在main函数中定义好矩阵和待检验的字符串;
然后在 matrix_path函数中写好逻辑,即循环检测每个方格的路径;
vertify_path函数是核心的判断函数,用来检测从某个方格开始是否有待检测路径;
最后,通过两个测试用例完成功能测试
注意:边界值测试可以令matrix或str指向空来测试,当然也可以令rows/cols小于等于0来判断。

#include<stdio.h>
#include<stdlib.h>   //包含malloc函数
#include<string.h>   //包含memset函数

#define true 1
#define false 0

int matrix_path(char* matrix, int rows,int cols, char* str) {

	if ((matrix == NULL) || (str == NULL) || (rows <= 0) || (cols <= 0))
		return false;
	
	int* visited;
	visited = (int*)malloc((rows * cols) * sizeof(int));
	memset(visited, 0, (rows * cols) * sizeof(int));

	// 测试visited数组是否初始化成功
	//for (int i = 0; i < rows; i++) {
	//	for (int j = 0; j < cols; j++) {
	//		printf("%d ", visited[i * cols + j]);
	//	}
	//	printf("\n");
	//}

	int pathLength = 0;

	for (int row = 0; row < rows; row++) {
		for (int col = 0; col < cols; col++) {
			if (vertify_path(matrix, rows, cols, str, row, col, pathLength, visited))
				return true;
		}
	}

	free(visited);

	return false;

}

int vertify_path(const char* matrix, int rows, int cols, char* str, int row, int col, int pathLength, int* visited) {

	if (visited == NULL)
		return false;

	if (str[pathLength] == '\0')
		return true;

	int path = false;

	if ((row >= 0) && (row < rows) && (col >= 0) && (col < cols) && (matrix[row * cols + col] == str[pathLength]) && (!visited[row * cols + col])) {

		pathLength++;
		visited[row * cols + col] = true;

		path = vertify_path(matrix, rows, cols, str, row, col - 1, pathLength, visited) ||
			vertify_path(matrix, rows, cols, str, row, col + 1, pathLength, visited) ||
			vertify_path(matrix, rows, cols, str, row - 1, col, pathLength, visited) ||
			vertify_path(matrix, rows, cols, str, row + 1, col, pathLength, visited);

		if (!path) {
			pathLength--;
			visited[row * cols + col] = false;
		}
	}

	return path;
}
//功能测试
int test1() {
	int rows = 3;
	int cols = 4;

	char matrix[3][4] = { 'a','b','t','g',\
		'c','f','c','s',\
		'j','d','e','h' };

	char str[5] = { 'b','f','c','e' };

	int  result = matrix_path(matrix, rows, cols, str);
	
	return result;
}

int test2() {
	int rows = 3;
	int cols = 4;

	char matrix[3][4] = { 'a','b','t','g',\
		'c','f','c','s',\
		'j','d','e','h' };

	char str[5] = { 'a','b','f','b' };

	int  result = matrix_path(matrix, rows, cols, str);
	
	return result;
}

void main() {

	int result1 = test1();

	if (result1)
		printf("find it!\n");
	else
		printf("This path no exist!\n");

	int result2 = test2();

	if (result2)
		printf("find it!\n");
	else
		printf("This path no exist!\n");
}

运行结果:
在这里插入图片描述
这道题的思路理解起来并不难,但我在编写过程中还是遇到了一些坑。现在把这些问题总结一下。

由于《剑指Offer》中的算法使用C++编写的,所以有些函数和标准C语言中不同,导致我的编程遇到了写没有预料到的bug。

memset

memset函数的头文件是string.h,它的作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零的最快的方法。
它的定义是:void *memset(void *s, int ch, size_t n);
用法:memset(s,ch,n);
意义:将s中当前位置后面的n个字符用ch替换。

为什么我要强调字符呢?
在这里插入图片描述
这个是百度百科里对该函数的解释。一开始,我初始化visited时使用了如下语句:

memset(visited, 0, rows * cols);

运行一下程序,同时把visited输出:
在这里插入图片描述
可以看到,只有前3个字符初始化成功,后面的都失败了。当我把初始化语句改为:

memset(visited, 0, (rows * cols) * sizeof(int));

在这里插入图片描述
可以看到visited初始化成功!

二维数组

由于计算机的内存是一维的,多维数组的元素应排成线性序列后存入存储器。在C语言中,数组按行优先顺序存储。
在本题中,我定义matrix时使用的是二维数组:

char matrix[3][4] = { 'a','b','t','g',\
		'c','f','c','s',\
		'j','d','e','h' };

而在调用过程中,我用一维数组的方式去调用:

matrix[row * cols + col]

程序正常运行,没有任何问题。所以这个二维只是便于我们理解,计算机内部的存储还是按照一维数组来的。

动态数组

已知数组规模的情况下,数组的定义为:

int a[常量表达式];   //定义一个固定长度的数组

其中,常量表达式可以是数字,也可以是宏定义的量。

比如:

//例一
int a[5];
//例二
#define NUM 5
int a[NUM];

若用变量表示则会出错:
在这里插入图片描述
在Visual Studio中提示num必须是常量。

若提前不知数组规模,可以使用动态数组。关于动态数组的定义:

int* matrix;                               //定义一个指针
int num;
scanf("%d\n",num);                         //用scanf函数接收num的值
matrix = (int*)malloc(num * sizeof(int));  //给matrix分配内存
for(int i = 0;i < num;i++){
	scanf("%d ",matrix[i]);                //给matrix分配数据
}

如果题目要求从键盘输入num和matrix的具体值,可用此方法初始化各部分的值。

malloc <–> free

由于malloc函数和free函数是成对出现的,因此在使用完后需使用free函数将matrix的空间释放,否则可能造成内存泄露。

发布了58 篇原创文章 · 获赞 3 · 访问量 2177

猜你喜欢

转载自blog.csdn.net/weixin_43936250/article/details/103950162