分析:
整体思路主要分为如下两部分:
主函数:
int main()
{
int arr[N][N] = {0};
int num = 0;
int ret = 0;
int sz = sizeof(arr)/sizeof(arr[0][0]);
srand((unsigned int)time(NULL));
InitArr(arr,sz); //初始化数组
printf("请输入要查找的数字:\n");
scanf("%d",&num);
ret = Find(arr,num,sz); //在杨氏矩阵中查找数字
if(ret == 1)
{
printf("找到了\n");
}
else
{
printf("没找到\n");
}
Print(arr); //输出杨氏矩阵
return 0;
}
一、初始化数组
杨氏矩阵的特点是:这个矩阵中的数字从左到右是递增的,从上到下也是递增的。
如:
左边矩阵是对角线有规律的,右边矩阵是我们所要实现的递增量为随机值的杨氏矩阵。
在写代码前,应该了解到,数组在内存中的存储是链式存储,如下图所示:
调试程序,对数组进行初始化,通过查看内存,可以看到数组在内存中的存储确实为链式存储,如下图:
我们可以利用数组的这一优点来初始化数组,通过一个指针,改变它的指向并修改它所指向的内容,每次的增量为随机量,即为我们所要求的增量为随机量的杨氏矩阵。
函数代码如下:
void InitArr(int arr[][N], int sz)
{
int i = 1;
int *p = &arr[0][0]; //使指针指向数组的第一个元素
*p = rand()%10+1; //给第一个元素赋随机值,随机值的范围从1-10
while(i<sz)
{
*(p+1) = *p + rand()%10+1; //给数组中的其余元素赋值,
//其元素值是前一个元素值加上随机增量值得到
p++;
i++;
}
}
二、查找元素
此阶段可以分为两种方法:
(一)二分查找法
同样根据数组的链式存储原理来寻找所要查的数字。
二分查找的思路如下:
left指针指向数组的开头元素,right指针指向数组的末尾元素,找到数组的中间位置为mid,如图:
如果,元素大于中间位置元素,left指向中间元素后一位置,中间值发生改变;
如果,元素小于中间位置元素,right指向中间元素前一位置,中间值发生改变;
直至找到所找元素或left大于right时结束循环。
函数代码如下:
int Find(int arr[][N], int num, int sz)
{
int *left = &arr[0][0];
int *right = &arr[N-1][N-1];
int mid = sz/2;
int ret = 0;
while(left<=right)
{
if(num<(*(left+mid)))
{
right = left+mid-1;
mid /= 2;
}
else if(num>(*(left+mid)))
{
left = left+mid+1;
mid += mid/2;
}
else if(num == (*(left+mid)))
{
ret = 1;
break;
}
}
return ret;
}
(二)杨氏矩阵查找法
这种方法先确定一个参考位置(参考位置确定为矩阵右上角元素),若要查找元素大于参考位置元素的话,向下查找;若要查找元素小于参考位置元素的话,向左查找;反复执行上述过程,直到找到该元素或者矩阵中元素查找完毕没有找到后结束循环。
如:要在下图所示矩阵中找到数字45,参考位置元素为17,45大于17,参考位置向下走;来到41上,45大于41,参考位置再向下走;来到57,45小于57,参考位置向左走;来到48,45小于48,参考位置再向下走;来到45,45等于45,找到该元素。
函数代码如下:
int Find(int arr[][N], int num, int sz)
{
int i = 0;
int j = N-1;
int ret = 0;
while(i<N && j>0)
{
if(num > arr[i][j])
{
i++;
}
else if(num < arr[i][j])
{
j--;
}
else
{
ret = 1;
break;
}
}
return ret;
}
整体代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 3
void InitArr(int arr[][N], int sz)
{
int i = 1;
int *p = &arr[0][0];
*p = rand()%10+1;
while(i<sz)
{
*(p+1) = *p + rand()%10+1;
p++;
i++;
}
}
void Print(int arr[][N])
{
int i = 0;
int j = 0;
for(i=0; i<N; i++)
{
for(j=0; j<N; j++)
{
printf("%3d ",arr[i][j]);
}
printf("\n");
}
}
//二分查找实现
int Find(int arr[][N], int num, int sz)
{
int *left = &arr[0][0];
int *right = &arr[N-1][N-1];
int mid = sz/2;
int ret = 0;
while(left<=right)
{
if(num<(*(left+mid)))
{
right = left+mid-1;
mid /= 2;
}
else if(num>(*(left+mid)))
{
left = left+mid+1;
mid += mid/2;
}
else if(num == (*(left+mid)))
{
ret = 1;
break;
}
}
return ret;
}
//杨氏矩阵查找实现
//int Find(int arr[][N], int num, int sz)
//{
// int i = 0;
// int j = N-1;
// int ret = 0;
// while(i<N && j>0)
// {
// if(num > arr[i][j])
// {
// i++;
// }
// else if(num < arr[i][j])
// {
// j--;
// }
// else
// {
// ret = 1;
// break;
// }
// }
// return ret;
//}
//
int main()
{
int arr[N][N] = {0};
int num = 0;
int ret = 0;
int sz = sizeof(arr)/sizeof(arr[0][0]);
srand((unsigned int)time(NULL));
InitArr(arr,sz);
printf("请输入要查找的数字:\n");
scanf("%d",&num);
ret = Find(arr,num,sz);
if(ret == 1)
{
printf("找到了\n");
}
else
{
printf("没找到\n");
}
Print(arr);
return 0;
}
运行结果