二维阵列峰值查找器的问题
Issues with 2D array peaks finder
我在教程的帮助下编写了这段代码,代码工作正常但它没有输出我应该得到的答案,它给我的答案是 (2,4) 和 (3,3)是 5530 和 5411,而我应该得到 (2,1)、(2,5) 和 (4,3),它们是 5560、5821 和 5831。代码应该只输出这 3 个值
代码如下
#include <stdio.h>
#define columns 7
#define rows 6
int arr[rows][columns] = {
{ 5039, 5127, 5238, 5259, 5248, 5310, 5299 },
{ 5150, 5392, 5410, 5401, 5320, 5820, 5321 },
{ 5290, 5560, 5490, 5421, 5530, 5831, 5210 },
{ 5110, 5429, 5430, 5411, 5459, 5630, 5319 },
{ 4920, 5129, 4921, 5821, 4722, 4921, 5129 },
{ 5023, 5129, 4822, 4872, 4794, 4862, 4245 },
};
void find_peaks(int arr[][columns]);
int main() {
find_peaks(arr);
return 0;
}
void find_peaks(int arr[][columns]) {
int curr = 0, peak_counter = 0;
for (int i = 0; i < rows - 1; i++)
for (int j = 1; j < columns - 1; j++) {
curr = arr[i][j];
for (int k = 0; k <= i + 1; k++) {
for (int l = j - 1; l <= j + 1; l++) {
if (arr[k][l] < curr)
peak_counter++;
if (arr[k][l] > curr)
curr = arr[i][j];
}
}
if (peak_counter == 8)
printf("peak at (%ld,%ld)\n", i, j);
peak_counter = 0;
}
}
非常感谢您的帮助。
这是我解决问题的方法。
#include <stdio.h>
#define columns 7
#define rows 6
int arr[rows][columns] = {
{ 5039, 5127, 5238, 5259, 5248, 5310, 5299 },
{ 5150, 5392, 5410, 5401, 5320, 5820, 5321 },
{ 5290, 5560, 5490, 5421, 5530, 5831, 5210 },
{ 5110, 5429, 5430, 5411, 5459, 5630, 5319 },
{ 4920, 5129, 4921, 5821, 4722, 4921, 5129 },
{ 5023, 5129, 4822, 4872, 4794, 4862, 4245 },
};
void find_peaks(int arr[][columns]);
int main() {
find_peaks(arr);
return 0;
}
void find_peaks(int arr[][columns]) {
int curr = 0;
for (int i = 1; i < rows - 1; i++)
for (int j = 1; j < columns - 1; j++) {
curr = arr[i][j];
//left, right, down, up, upper_left, upper_right, lower_left, lower_right
if (arr[i][j-1] < curr && arr[i][j+1] < curr && arr[i-1][j] < curr && arr[i+1][j] < curr && arr[i-1][j-1] < curr && arr[i-1][j+1] < curr && arr[i+1][j-1] < curr && arr[i+1][j+1] < curr) {
printf("peak at (%d,%d)\n", i, j);
}
}
}
您查找局部最大值的代码存在一些问题:
- 外循环应该从
i = 1
开始
- 第三个循环应该从
k = i - 1
开始
- 在内部循环中更新
curr
似乎没有必要。一旦测试失败并且 k != i
和 l != j
,您可以立即中断内部循环,但这些额外的测试可能会损害性能而不是提高性能。按照编码,内部循环应该编译成高效的无分支代码。
- 对于
printf("peak at (%ld,%ld)\n", i, j);
中的 int
个参数,您应该使用 %d
- 宏
columns
和 rows
. 使用大写是惯用的
这是修改后的版本:
#include <stdio.h>
#define COLUMNS 7
#define ROWS 6
int array[ROWS][COLUMNS] = {
{ 5039, 5127, 5238, 5259, 5248, 5310, 5299 },
{ 5150, 5392, 5410, 5401, 5320, 5820, 5321 },
{ 5290, 5560, 5490, 5421, 5530, 5831, 5210 },
{ 5110, 5429, 5430, 5411, 5459, 5630, 5319 },
{ 4920, 5129, 4921, 5821, 4722, 4921, 5129 },
{ 5023, 5129, 4822, 4872, 4794, 4862, 4245 },
};
void find_peaks(int arr[][COLUMNS]) {
for (int i = 1; i < ROWS - 1; i++) {
for (int j = 1; j < COLUMNS - 1; j++) {
int peak_counter = 0;
int curr = arr[i][j];
for (int k = i - 1; k <= i + 1; k++) {
for (int l = j - 1; l <= j + 1; l++) {
if (arr[k][l] < curr)
peak_counter++;
}
}
if (peak_counter == 8)
printf("peak at (%d,%d): %d\n", i, j, curr);
}
}
}
int main() {
find_peaks(array);
return 0;
}
输出:
peak at (2,1): 5560
peak at (2,5): 5831
peak at (4,3): 5821
我不知道你的算法是如何工作的,所以我自己写了一个。
#include <stdio.h>
#define COLUMNS 7
#define ROWS 6
int arr[ROWS][COLUMNS] = {
{ 5039, 5127, 5238, 5259, 5248, 5310, 5299 },
{ 5150, 5392, 5410, 5401, 5320, 5820, 5321 },
{ 5290, 5560, 5490, 5421, 5530, 5831, 5210 },
{ 5110, 5429, 5430, 5411, 5459, 5630, 5319 },
{ 4920, 5129, 4921, 5821, 4722, 4921, 5129 },
{ 5023, 5129, 4822, 4872, 4794, 4862, 4245 },
};
void find_peaks() {
int get (int x, int y) {
if (x < 0 || x >= ROWS) return -1;
if (y < 0 || y >= COLUMNS) return -1;
return arr[y][x];
};
for (int y = 0; y < ROWS; y++) {
for (int x = 0; x < COLUMNS; x++) {
int t = arr[y][x];
if (t <= get(x + 1, y)) continue;
if (t <= get(x - 1, y)) continue;
if (t <= get(x, y + 1)) continue;
if (t <= get(x, y - 1)) continue;
if (t <= get(x + 1, y + 1)) continue;
if (t <= get(x - 1, y + 1)) continue;
if (t <= get(x + 1, y - 1)) continue;
if (t <= get(x - 1, y - 1)) continue;
printf("Peak of %d at (%d, %d)\n", t, x, y);
};
};
};
int main() {
find_peaks();
return 0;
};
如果您实际上并不关心在数组边缘找到峰值,那么您不需要 get()
包装器来检查您是否没有超出数组边界,但是您可以只需让循环从 1 转到 limit-1 即可。如果您不关心对角线,您也可以删除第二组四个 if () continue
语句,但鉴于您指出的正确答案,看来您确实关心。
我在教程的帮助下编写了这段代码,代码工作正常但它没有输出我应该得到的答案,它给我的答案是 (2,4) 和 (3,3)是 5530 和 5411,而我应该得到 (2,1)、(2,5) 和 (4,3),它们是 5560、5821 和 5831。代码应该只输出这 3 个值
代码如下
#include <stdio.h>
#define columns 7
#define rows 6
int arr[rows][columns] = {
{ 5039, 5127, 5238, 5259, 5248, 5310, 5299 },
{ 5150, 5392, 5410, 5401, 5320, 5820, 5321 },
{ 5290, 5560, 5490, 5421, 5530, 5831, 5210 },
{ 5110, 5429, 5430, 5411, 5459, 5630, 5319 },
{ 4920, 5129, 4921, 5821, 4722, 4921, 5129 },
{ 5023, 5129, 4822, 4872, 4794, 4862, 4245 },
};
void find_peaks(int arr[][columns]);
int main() {
find_peaks(arr);
return 0;
}
void find_peaks(int arr[][columns]) {
int curr = 0, peak_counter = 0;
for (int i = 0; i < rows - 1; i++)
for (int j = 1; j < columns - 1; j++) {
curr = arr[i][j];
for (int k = 0; k <= i + 1; k++) {
for (int l = j - 1; l <= j + 1; l++) {
if (arr[k][l] < curr)
peak_counter++;
if (arr[k][l] > curr)
curr = arr[i][j];
}
}
if (peak_counter == 8)
printf("peak at (%ld,%ld)\n", i, j);
peak_counter = 0;
}
}
非常感谢您的帮助。
这是我解决问题的方法。
#include <stdio.h>
#define columns 7
#define rows 6
int arr[rows][columns] = {
{ 5039, 5127, 5238, 5259, 5248, 5310, 5299 },
{ 5150, 5392, 5410, 5401, 5320, 5820, 5321 },
{ 5290, 5560, 5490, 5421, 5530, 5831, 5210 },
{ 5110, 5429, 5430, 5411, 5459, 5630, 5319 },
{ 4920, 5129, 4921, 5821, 4722, 4921, 5129 },
{ 5023, 5129, 4822, 4872, 4794, 4862, 4245 },
};
void find_peaks(int arr[][columns]);
int main() {
find_peaks(arr);
return 0;
}
void find_peaks(int arr[][columns]) {
int curr = 0;
for (int i = 1; i < rows - 1; i++)
for (int j = 1; j < columns - 1; j++) {
curr = arr[i][j];
//left, right, down, up, upper_left, upper_right, lower_left, lower_right
if (arr[i][j-1] < curr && arr[i][j+1] < curr && arr[i-1][j] < curr && arr[i+1][j] < curr && arr[i-1][j-1] < curr && arr[i-1][j+1] < curr && arr[i+1][j-1] < curr && arr[i+1][j+1] < curr) {
printf("peak at (%d,%d)\n", i, j);
}
}
}
您查找局部最大值的代码存在一些问题:
- 外循环应该从
i = 1
开始
- 第三个循环应该从
k = i - 1
开始
- 在内部循环中更新
curr
似乎没有必要。一旦测试失败并且k != i
和l != j
,您可以立即中断内部循环,但这些额外的测试可能会损害性能而不是提高性能。按照编码,内部循环应该编译成高效的无分支代码。 - 对于
printf("peak at (%ld,%ld)\n", i, j);
中的 - 宏
columns
和rows
. 使用大写是惯用的
int
个参数,您应该使用 %d
这是修改后的版本:
#include <stdio.h>
#define COLUMNS 7
#define ROWS 6
int array[ROWS][COLUMNS] = {
{ 5039, 5127, 5238, 5259, 5248, 5310, 5299 },
{ 5150, 5392, 5410, 5401, 5320, 5820, 5321 },
{ 5290, 5560, 5490, 5421, 5530, 5831, 5210 },
{ 5110, 5429, 5430, 5411, 5459, 5630, 5319 },
{ 4920, 5129, 4921, 5821, 4722, 4921, 5129 },
{ 5023, 5129, 4822, 4872, 4794, 4862, 4245 },
};
void find_peaks(int arr[][COLUMNS]) {
for (int i = 1; i < ROWS - 1; i++) {
for (int j = 1; j < COLUMNS - 1; j++) {
int peak_counter = 0;
int curr = arr[i][j];
for (int k = i - 1; k <= i + 1; k++) {
for (int l = j - 1; l <= j + 1; l++) {
if (arr[k][l] < curr)
peak_counter++;
}
}
if (peak_counter == 8)
printf("peak at (%d,%d): %d\n", i, j, curr);
}
}
}
int main() {
find_peaks(array);
return 0;
}
输出:
peak at (2,1): 5560
peak at (2,5): 5831
peak at (4,3): 5821
我不知道你的算法是如何工作的,所以我自己写了一个。
#include <stdio.h>
#define COLUMNS 7
#define ROWS 6
int arr[ROWS][COLUMNS] = {
{ 5039, 5127, 5238, 5259, 5248, 5310, 5299 },
{ 5150, 5392, 5410, 5401, 5320, 5820, 5321 },
{ 5290, 5560, 5490, 5421, 5530, 5831, 5210 },
{ 5110, 5429, 5430, 5411, 5459, 5630, 5319 },
{ 4920, 5129, 4921, 5821, 4722, 4921, 5129 },
{ 5023, 5129, 4822, 4872, 4794, 4862, 4245 },
};
void find_peaks() {
int get (int x, int y) {
if (x < 0 || x >= ROWS) return -1;
if (y < 0 || y >= COLUMNS) return -1;
return arr[y][x];
};
for (int y = 0; y < ROWS; y++) {
for (int x = 0; x < COLUMNS; x++) {
int t = arr[y][x];
if (t <= get(x + 1, y)) continue;
if (t <= get(x - 1, y)) continue;
if (t <= get(x, y + 1)) continue;
if (t <= get(x, y - 1)) continue;
if (t <= get(x + 1, y + 1)) continue;
if (t <= get(x - 1, y + 1)) continue;
if (t <= get(x + 1, y - 1)) continue;
if (t <= get(x - 1, y - 1)) continue;
printf("Peak of %d at (%d, %d)\n", t, x, y);
};
};
};
int main() {
find_peaks();
return 0;
};
如果您实际上并不关心在数组边缘找到峰值,那么您不需要 get()
包装器来检查您是否没有超出数组边界,但是您可以只需让循环从 1 转到 limit-1 即可。如果您不关心对角线,您也可以删除第二组四个 if () continue
语句,但鉴于您指出的正确答案,看来您确实关心。