将0移到MxN数组中每一列的顶部

时间:2019-05-11 18:08:03

标签: c multidimensional-array

我有一个NxM矩阵(尺寸由用户设置),并且我想要一个函数将0移到每一列的顶部,而其余整数保持原样。看例子:

将0s移动到MxN数组中每列的顶部

enter image description here

移动0之后,我希望拥有:

enter image description here

有人请在下面更正我的zerototopMatrix函数:

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h>

void printMatrix(int (*arr), int rows, int cols,int level)
{
    int i, j;

    printf("\n");
    printf("\n");

    printf("The matrix elements are:\n   ");
    for (i = 0; i < cols+level; i++) {
        printf("%d ", i+1);
    } 
    printf("\n");
    for (i = 0; i < (cols*2+1+level); i++) {
        printf("-");
    } 
    printf("-\n");
    for (i = 0; i < rows+level; i++) {
        printf("%d| ", i+1);
        for (j = 0; j < cols+level; j++) {
            printf("%d ", *(arr + i*cols + j)); 
        }     
        printf("\n");
    }
}

void zerototopMatrix(int (*arr), int rows, int cols,int level)
{
    int i, j;

    printf("\n");
    printf("\n");

    int count = 0,temp = 0;

    for (j = 0; j < cols+level; j++) {
        for (i = 0; i < rows+level; i++) {
            if (*(arr + i*cols + j)==0)
            {
                (*(arr + i*cols + j)= (*(arr + count*cols + j)));
                (*(arr + count*cols + j))=0;
                count++;
            }
        }     
    }
}

int main() { 

    int number;

    srand ( time(NULL) );
    int level = 0;

    int row,col,colors;
    int points = 0;


    printf("How many rows:\n");
    scanf("%d", &row);

    printf("How many columns:\n");
    scanf("%d", &col);

    printf("How many colors:\n");
    scanf("%d", &colors);

    int *arr = (int *)malloc(row * col * sizeof(int)); 
    int i, j; 

    for (i = 0; i < row+level; i++) 
        for (j = 0; j < col+level; j++) {
            number = rand() % colors ;
            *(arr + i*col + j) = number;   
        }

    printMatrix(arr, row, col,level);

    printf("\n\nMove 0s to top:\n");
    zerototopMatrix(arr, row, col,level);

    printMatrix(arr, row, col,level);

    free(arr); 
    return 0; 
}

2 个答案:

答案 0 :(得分:1)

最初的想法是创建一个临时缓冲区来存储所有非零元素:

void zeroToTopMatrix(int *arr, int rows, int cols, int level) {
    int i, j;

    for (j = 0; j < cols + level; j++) {
        int tmp[rows];
        int tmpLen = 0;

        for (i = 0; i < rows + level; i++) {
            if (arr[i*cols+j]) {
                tmp[tmpLen++] = arr[i*cols+j];
            }
        }

        for (i = 0; i < rows - tmpLen; i++) {
            arr[i*cols+j] = 0;
        }

        for (int k = 0; i < rows; i++) {
            arr[i*cols+j] = tmp[k++];
        }
    }
}

但是Eric Postpischil的建议要聪明得多-从每列的底部移动到顶部,根据需要执行交换,并在顶部填充零。这是代码:

void zeroToTopMatrix(int *arr, int rows, int cols, int level) {
    int i, j;

    for (j = 0; j < cols + level; j++) {
        int k = rows + level - 1;

        for (i = k; i >= 0; i--) {
            if (arr[i*cols+j]) {
                arr[k--*cols+j] = arr[i*cols+j];
            }
        }

        while (k >= 0) {
            arr[k--*cols+j] = 0;
        }
    }
}

这是一个完整的测试:

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h>

void zeroToTopMatrix(int *arr, int rows, int cols, int level) {
    int i, j;

    for (j = 0; j < cols + level; j++) {
        int k = rows + level - 1;

        for (i = k; i >= 0; i--) {
            if (arr[i*cols+j]) {
                arr[k--*cols+j] = arr[i*cols+j];
            }
        }

        while (k >= 0) {
            arr[k--*cols+j] = 0;
        }
    }
}


void printMatrix(int *arr, int rows, int cols, int level) {
    int i, j;

    printf("\n");
    printf("\n");
    printf("The matrix elements are:\n   ");

    for (i = 0; i < cols + level; i++) {
        printf("%d ", i + 1);
    } 

    printf("\n");

    for (i = 0; i < (cols * 2 + 1 + level); i++) {
        printf("-");
    } 

    printf("-\n");

    for (i = 0; i < rows + level; i++) {
        printf("%d| ", i + 1);

        for (j = 0; j < cols + level; j++) {
            printf("%d ", *(arr + i * cols + j)); 
        }     

        printf("\n");
    }
}

int main() { 
    int i, j; 
    int number;
    int level = 0;
    int row, col, colors;
    int points = 0;

    srand(15/*time(NULL)*/);
    row = 5;
    col = 9;
    colors = 5;

    int *arr = malloc(row * col * sizeof(int)); 

    for (i = 0; i < row + level; i++) {
        for (j = 0; j < col + level; j++) {
            number = rand() % colors;
            *(arr + i * col + j) = number;   
        }
    }

    printMatrix(arr, row, col, level);
    zeroToTopMatrix(arr, row, col, level);
    printMatrix(arr, row, col, level);

    free(arr); 
    return 0; 
}

输出:

The matrix elements are:
   1 2 3 4 5 6 7 8 9
--------------------
1| 3 0 2 0 1 0 4 2 3
2| 3 3 2 4 4 0 0 4 2
3| 4 3 0 0 3 1 0 1 3
4| 1 0 3 0 0 0 4 0 3
5| 0 0 1 3 0 4 3 1 0


The matrix elements are:
   1 2 3 4 5 6 7 8 9
--------------------
1| 0 0 0 0 0 0 0 0 0
2| 3 0 2 0 0 0 0 2 3
3| 3 0 2 0 1 0 4 4 2
4| 4 3 3 4 4 1 4 1 3
5| 1 3 1 3 3 4 3 1 3

一些其他提示:

  • 有时指针算术很优雅,但是在这种情况下,将2d数组打包到1d中使用数组索引似乎更清楚。
  • 无需在C中强制转换malloc的结果。

答案 1 :(得分:1)

只需将非零元素移动到数组的底部,对每一列从下到上进行操作即可完成:

  • 在数组的底部设置源索引S和目标索引D。
  • 迭代并递减S,直到S通过数组的顶部:
    • 如果元素S不为零,则将元素S复制到元素D并递减D。
  • 迭代并递减D,直到D通过数组的顶部:
    • 将元素D设置为零。

代码是:

void zeroToTopMatrix(int *arr, int rows, int cols, int level)
{
    //  Iterate through columns.
    for (int c = 0; c < cols + level; ++c)
    {
        //  Start destination index at bottom of column.
        int D = rows + level;

        //  Iterate source index backwards through column, skipping zeros.
        for (int S = rows + level - 1; 0 <= S; --S)
            if (arr[S*cols + c] != 0)
                arr[--D*cols + c] = arr[S*cols + c];

        //  Fill in top elements with skipped zeros.
        while (0 < D)
            arr[--D*cols + c] = 0;
    }
}

我将level变量保留为原始代码中的变量,但是它看起来不合适,并且如果非零,则可能会破坏代码。