地址为:p + i*n + j;
从以上可以看出,如果我们省略了第二维或者更高维的大小,编译器将不知道如何正确
的寻址。但是我们在编写程序的时候却需要用到各个维数都不固定的二维数组作为参数,
这就难办了,编译器不能识别阿,怎么办呢?不要着急,编译器虽然不能识别,但是我们
完全可以不把它当作一个二维数组,而是把它当作一个普通的指针,再另外加上两个参数
指明各个维数,然后我们为二维数组手工寻址,这样就达到了将二维数组作为函数的参数
传递的目的,根据这个思想,我们可以把维数固定的参数变为维数随即的参数,例如:
void Func(int array[3][10]); void Func(int array[][10]); 变为:
void Func(int **array, int m, int n);
在转变后的函数中,array[i][j]这样的式子是不对的(不信,大家可以试一下),因为
编译器不能正确的为它寻址,所以我们需要模仿编译器的行为把array[i][j]这样的式子 手工转变为
*((int*)array + n*i + j);
在调用这样的函数的时候,需要注意一下,如下面的例子: int a[3][3] = {
{1, 1, 1}, {2, 2, 2}, {3, 3, 3} };
Func(a, 3, 3);
根据不同编译器不同的设置,可能出现warning 或者error,可以进行强制转换如下调用
:
Func((int**)a, 3, 3);
其实数组和二维数组原理是一样的,大家可以自己扩充的数组,这里不再赘述
。写到这里,我先向看了这篇文章后悔的人道歉,浪费你的时间了。下面是一个完整的例
子程序,这个例子程序的主要功能是求一个图中某个顶点到其他顶点的最短路经,图是以
邻接矩阵的形式存放的(也就是一个二维数组),其实这个函数也是挺有用的,但是我们这
篇文章的重点在于将二维数组作为函数的参数传递。
完整的例子程序包括三个文件,在Microsoft Visual C++ 6.0下调试通过。如下:
// // mian.c 为主程序入口,并且调用了示范了如何调用求一个图中某个顶点到其他顶点
的最短路经 // 的函数 //
#include \"short.h\" #include int main() {
int i = 0, v = 0;
float AdjoinMatrix[5][5]= {
{0, 10,NO_PATH,30,100},
{NO_PATH,0,50,NO_PATH,NO_PATH}, {NO_PATH,NO_PATH,0,NO_PATH,10}, {NO_PATH,NO_PATH,20,0,60},
{NO_PATH,NO_PATH,NO_PATH,NO_PATH,0} };
int Path[5];
float Length[5];
ShortestPath(AdjoinMatrix, Length, Path, 5, 0);
for(i = 1; i < 5; i++) {
v = i;
while(v != 0) {
printf(\"%d \v = Path[v]; }
printf(\"%d\\n\}
return 0; }
//
// ShortestPath.h 中定义了求一个图中某个顶点到其他顶点的最短路经的函数,还定
义了一个
// 宏,#define NO_PATH 0x00ffffff,如果图中的两个顶点之间的直接路径的长度为
NO_PATH,
// 表示图中两个顶点是不直接相通的。 //
#ifndef INCLUDE_SHORTESTPATH_H #define INCLUDE_SHORTESTPATH_H
#define IN #define OUT
#define NO_PATH 0x00ffffff /*++
Abstract:
该函数的功能是求得一个图中的某个顶点到其他所有顶点的最短路经,及其最 短路经的长度
Returen value:
类型是int,含义如下 0 成功
1 资源不够
Examples:
//你有一个图的邻接矩阵如AdjoinMatrix[n][n]和数组 Path[n], Length[n](n为图顶点的个数,
//然后你可以如下调用:ShortestPath(AdjoinMatrix, Length, Path, 5, 0);
//调用后,Path[n]中存放最短路径,Length[n]中存放着最 短路径的长度
//下面的例子中我们求得从0顶点到其他定点的最短路经及 其长度
float AdjoinMatrix[5][5]= {
{0, 10,NO_PATH,30,100},
{NO_PATH,0,50,NO_PATH,NO_PATH}, {NO_PATH,NO_PATH,0,NO_PATH,10}, {NO_PATH,NO_PATH,20,0,60},
{NO_PATH,NO_PATH,NO_PATH,NO_PATH,0} };
int Path[5];
float Length[5];
ShortestPath(AdjoinMatrix, Length, Path, 5, 0);
int i = 0, int v =0; for(i = 1; i < 5; i++) {
v = i;
while(v != 0) {
printf(\"%d \v = Path[v]; }
printf(\"%d\\n\}
--*/
int ShortestPath(
IN float **AdjoinMatrix, //存放图的邻接矩阵,是 一个二维数组
OUT float *Length, //用于返回到各 个点的最短路经的长度
OUT int *Path, //用于返回最短
路经,Path[i]表示在最短路经上顶点i前面的顶点 IN int VertexNum, //顶点的个数 IN int Vertex //起始顶点 ); #endif
//
// ShortestPath.c 中实现了求一个图中某个顶点到其他顶点的最短路经的函数。 //
#include \"ShortestPath.h\"
#include /*++Abstract:
该函数的功能是求得一个图中的某个顶点到其他所有顶点的最短路经,及其最短 路经的长度
Returen value:
类型是int,含义如下 0 成功
1 资源不够 --*/
int ShortestPath(
IN float **AdjoinMatrix, //存放图的邻接矩阵,是 一个二维数组
OUT float *Length, //用于返回到各
个点的最短路经的长度
OUT int *Path, //用于返回最短
路经,Path[i]表示在最短路经上顶点i前面的顶点 IN int VertexNum, //顶点的个数 IN int Vertex //起始顶点 ) {
int i = 0, j = 0, w = 0; //
// 已经在最短路经中的点的集合,如果VertexSet[i]不为0,则表示第 i个点在该集合中 //
int *VertexSet = (int*)malloc(VertexNum); if(VertexSet == NULL) {
return 1; //缺乏内存资源 } //
// 初始化 //
for(i = 0; i < VertexNum; i++) {
Length[i] = *((float*)AdjoinMatrix + Vertex*VertexNum + i);
VertexSet[i]=0;
if(i != Vertex && Length[i] < NO_PATH) {
Path[i]=Vertex; } else {
Path[i] = -1; } }
VertexSet[Vertex] = 1; Length[Vertex] = 0; //
// 求得最短路经 //
for(i = 0; i < VertexNum-1; i++) {
float min = NO_PATH; int u = Vertex;
for(j = 0; j < VertexNum; j++) {
if( !VertexSet[j] && Length[j] < min) {
u = j;
min = Length[j]; } }
VertexSet[u] = 1;
for(w = 0; w < VertexNum; w++) {
if(!VertexSet[w] && *((float*)AdjoinMatrix +
u*VertexNum + w) < NO_PATH && Length[u]+*((float*)AdjoinMatrix + u*VertexNum +
w) < Length[w]) {
Length[w] = Length[u] +
*((float*)AdjoinMatrix + u*VertexNum + w); Path[w] = u; } } }
return 0; }