如何将零移动到 Pascal 矩阵的底部?

How to move zeros to the bottom of a matrix in pascal?

我有一个矩阵,例如:

xy 1 2 3 4 5
-------------
1| 1 1 1 2 3
2| 3 0 2 0 0
3| 2 2 1 3 0
4| 3 1 3 2 3
5| 1 0 0 1 0
6| 0 2 1 3 1
-------------

并且我想将所有零推到每列的底部,如下所示:

xy 1 2 3 4 5
-------------
1| 1 1 1 2 3
2| 3 2 2 3 3
3| 2 1 1 2 1
4| 3 2 3 1 0
5| 1 0 1 3 0
6| 0 0 0 0 0
-------------

我做了这个程序,但不能正常工作,有时它在某些列上工作,但在其他列的中间留下零

procedure MoveZeros(var matnum:matriz);
var x,y,aux:integer;
begin

    for y:= min to maxcol do begin

        for x:= min to maxfil do begin

            if (matnum[x,y] = 0) then begin 
                
                matnum[x,y] := matnum[x+1,y];
                matnum[x+1,y]:=0;

            end;
                
        end;
    end;

end;

有什么想法吗?

如果您一次看不到一个以上的 0,您的方法就会奏效 - 如果您这样做了,那么只有序列中的最后一个会被向下移动。

这里的技巧是使用一个单独的指针来保存我们见过的最高未填充零的位置。然后,当我们看到一个非零值时,我们将它移动到这个位置并增加指针。一旦我们到达列的底部,如果这个指针不在末尾,那么我们写入 0 并递增指针直到它结束。

希望将这个简单的 Java 代码转换为 Pascal 不会太困难

int[][] a = {{1, 1, 1, 2, 3},
             {3, 0, 2, 0, 0},
             {2, 2, 1, 3, 0},
             {3, 1, 3, 2, 3},
             {1, 0, 0, 1, 0},
             {0, 2, 1, 3, 1},       
            };


for(int y=0; y<a[0].length; y++)
{
    int z = 0;
    for(int x=0; x<a.length; x++)
    {
        if(a[x][y] != 0)
        {
            if(z < x) 
                a[z][y] = a[x][y];
            z += 1;
        }               
    }
    for(; z<a.length; z++)          
        a[z][y] = 0;
}

for(int[] row : a)
    System.out.println(Arrays.toString(row));    

输出:

[1, 1, 1, 2, 3]
[3, 2, 2, 3, 3]
[2, 1, 1, 2, 1]
[3, 2, 3, 1, 0]
[1, 0, 1, 3, 0]
[0, 0, 0, 0, 0]

对于每一列,检查每个元素并列出非零元素。然后按顺序重写非零元素的列,其余位置写零。

如果你真的想“推”下零,或者更确切地说“拉”,那么你需要在一列中上下 运行。这看起来像那样(扩展 Pascal,ISO 10206):

procedure pullZerosDown(var matrix: array[
        columnMinimum..columnMaximum: integer;
        rowMinimum..rowMaximum: integer
    ] of integer);
var
    x: type of columnMinimum;
    y: type of rowMinimum;
begin
    for x := columnMinimum to columnMaximum do
    begin
        y := rowMaximum;
        while y > rowMinimum do
        begin
            if matrix[x, y] = 0 then
            begin
                for y := y to rowMaximum - 1 do
                begin
                    matrix[x, y] := matrix[x, y + 1];
                    matrix[x, y + 1] := 0;
                end;
                
                repeat
                begin
                    y := y - 1;
                end
                until matrix[x, y] <> 0;
            end
            else
            begin
                y := y - 1;
            end;
        end;
    end;
end;

它的效率肯定较低,但它确实有效。您不需要像@RaffleBuffle 建议的那样额外的“指针”变量。这段代码演示了,你可以隐式存储信息,只需你在哪里你在哪里,你的PC(程序计数器)在哪里。

如果我理解,您想将零移动到列的底部,所以:

Type Matrix = Array [RowMin..RowMax, ColMin..ColMax] of integer;
procedure MoveZeros(var matnum:matriz);
var x,y,Bottom:integer;
begin
    for y:= colmin to colmax do 
    begin
       Bottom := RowMax;
       while (Matnum[Bottom,y] = 0) and (Bottom > RowMin) do {Find last non-zero}
           Bottom := Pred(Bottom); {or Dec(Bottom); or Bottom := Bottom-1; }
       X := Rowmin;
       repeat
           if (matnum[x,y] = 0) then 
            begin  {interchange}
                matnum[x,y] := matnum[bottom,y];
                matnum[bottom,y]:=0;
                Bottom  := Pred(Bottom); { reduce search size }
            end;                
            X := Succ(X); {Move down the list}
       until X>Bottom;
    end;
end;

好处是,当它向下移动零时,它排除了我们知道为零的条目。因此,随着它的发展,它可能会变得更快。