按行遍历和按列遍历哪一个更快一些?

如有错误欢迎指正!

今天(9月7日)上午《计算机操作系统》课上老师提出一个问题:

按行遍历和按列遍历哪一个运行时间更短一些?

我周围的同学大部分认为按行遍历更快一些,可能是受到C语言写for循环时习惯于先循环行再循环列的影响。
之前看过一篇文章,里面提到了按行遍历和按列遍历哪个快取决于使用的语言类型,同时,在做深圳杯大作业的时候,通过查阅资料偶然发现了MATLAB中优化代码运行时间的其中一个方法是for循环要用按列遍历。下面用程序检验一下。
v1:C语言版本,分别输出不同大小矩阵、不同遍历方式下的运行时间。

#include<stdio.h>
#include<time.h>
int a[20005][20005]={
    
    0};
int main()
{
    
    
    double s1,s2;
    int i,j;
    s1=clock();
    for(i=1;i<=10;i++){
    
    
        for(j=1;j<=10;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("10*10数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=10;i++){
    
    
        for(j=1;j<=10;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("10*10数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=100;i++){
    
    
        for(j=1;j<=100;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("100*100数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=100;i++){
    
    
        for(j=1;j<=100;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("100*100数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=500;i++){
    
    
        for(j=1;j<=500;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("500*500数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=500;i++){
    
    
        for(j=1;j<=500;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("500*500数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=1000;i++){
    
    
        for(j=1;j<=1000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("1000*1000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=1000;i++){
    
    
        for(j=1;j<=1000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("1000*1000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=2000;i++){
    
    
        for(j=1;j<=2000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("2000*2000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=2000;i++){
    
    
        for(j=1;j<=2000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("2000*2000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=3000;i++){
    
    
        for(j=1;j<=3000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("3000*3000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=3000;i++){
    
    
        for(j=1;j<=3000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("3000*3000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=4000;i++){
    
    
        for(j=1;j<=4000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("4000*4000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=4000;i++){
    
    
        for(j=1;j<=4000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("4000*4000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=5000;i++){
    
    
        for(j=1;j<=5000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("5000*5000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=5000;i++){
    
    
        for(j=1;j<=5000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("5000*5000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=6000;i++){
    
    
        for(j=1;j<=6000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("6000*6000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=6000;i++){
    
    
        for(j=1;j<=6000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("6000*6000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=7000;i++){
    
    
        for(j=1;j<=7000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("7000*7000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=7000;i++){
    
    
        for(j=1;j<=7000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("7000*7000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=8000;i++){
    
    
        for(j=1;j<=8000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("8000*8000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=8000;i++){
    
    
        for(j=1;j<=8000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("8000*8000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=9000;i++){
    
    
        for(j=1;j<=9000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("9000*9000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=9000;i++){
    
    
        for(j=1;j<=9000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("9000*9000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=10000;i++){
    
    
        for(j=1;j<=10000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("10000*10000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=10000;i++){
    
    
        for(j=1;j<=10000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("10000*10000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=12000;i++){
    
    
        for(j=1;j<=12000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("12000*12000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=12000;i++){
    
    
        for(j=1;j<=12000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("12000*12000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=14000;i++){
    
    
        for(j=1;j<=14000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("14000*14000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=14000;i++){
    
    
        for(j=1;j<=14000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("14000*14000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=16000;i++){
    
    
        for(j=1;j<=16000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("16000*16000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=16000;i++){
    
    
        for(j=1;j<=16000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("16000*16000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=18000;i++){
    
    
        for(j=1;j<=18000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("18000*18000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=18000;i++){
    
    
        for(j=1;j<=18000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("18000*18000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=20000;i++){
    
    
        for(j=1;j<=20000;j++){
    
    
            a[i][j]=1;
        }
    }
    s2=clock();
    printf("20000*20000数组按行遍历运行时间:%.12f s\n",(s2-s1)/CLOCKS_PER_SEC);
    s1=clock();
    for(i=1;i<=20000;i++){
    
    
        for(j=1;j<=20000;j++){
    
    
            a[j][i]=1;
        }
    }
    s2=clock();
    printf("20000*20000数组按列遍历运行时间:%.12f s\n\n",(s2-s1)/CLOCKS_PER_SEC);
    return 0;
}

运行结果:

10*10数组按行遍历运行时间:0.000000000000 s
10*10数组按列遍历运行时间:0.000000000000 s

100*100数组按行遍历运行时间:0.000000000000 s
100*100数组按列遍历运行时间:0.000000000000 s

500*500数组按行遍历运行时间:0.002000000000 s
500*500数组按列遍历运行时间:0.000000000000 s

1000*1000数组按行遍历运行时间:0.001000000000 s
1000*1000数组按列遍历运行时间:0.003000000000 s

2000*2000数组按行遍历运行时间:0.008000000000 s
2000*2000数组按列遍历运行时间:0.023000000000 s

3000*3000数组按行遍历运行时间:0.011000000000 s
3000*3000数组按列遍历运行时间:0.064000000000 s

4000*4000数组按行遍历运行时间:0.018000000000 s
4000*4000数组按列遍历运行时间:0.117000000000 s

5000*5000数组按行遍历运行时间:0.025000000000 s
5000*5000数组按列遍历运行时间:0.181000000000 s

6000*6000数组按行遍历运行时间:0.037000000000 s
6000*6000数组按列遍历运行时间:0.263000000000 s

7000*7000数组按行遍历运行时间:0.042000000000 s
7000*7000数组按列遍历运行时间:0.372000000000 s

8000*8000数组按行遍历运行时间:0.055000000000 s
8000*8000数组按列遍历运行时间:0.469000000000 s

9000*9000数组按行遍历运行时间:0.067000000000 s
9000*9000数组按列遍历运行时间:0.602000000000 s

10000*10000数组按行遍历运行时间:0.074000000000 s
10000*10000数组按列遍历运行时间:0.728000000000 s

12000*12000数组按行遍历运行时间:0.127000000000 s
12000*12000数组按列遍历运行时间:1.052000000000 s

14000*14000数组按行遍历运行时间:0.176000000000 s
14000*14000数组按列遍历运行时间:1.429000000000 s

16000*16000数组按行遍历运行时间:0.203000000000 s
16000*16000数组按列遍历运行时间:1.870000000000 s

18000*18000数组按行遍历运行时间:0.251000000000 s
18000*18000数组按列遍历运行时间:2.383000000000 s

20000*20000数组按行遍历运行时间:0.274000000000 s
20000*20000数组按列遍历运行时间:2.927000000000 s

当数组大小较小时,按行遍历和按列遍历的时间差不多;随着数组大小的增大,二者的运行时间均有增长,但是增长幅度不同。显然按行遍历的增长幅度要小于按列遍历,当数组大小在10000*10000以上时,按列遍历的运行时间超过1秒,在OJ中提交会TLE,而按行遍历的运行时间仍在可接受范围内。
v2:MATLAB R2019b版本,分别输出不同大小矩阵、不同遍历方式下的运行时间。

a=zeros(20000,20000);
%10*10
disp('10*10按行遍历:')
tic
for i=1:10
    for j=1:10
        a(i,j)=1;
    end
end
toc
disp('10*10按列遍历:')
tic
for j=1:10
    for i=1:10
        a(i,j)=1;
    end
end
toc
%100*100
disp('100*100按行遍历:')
tic
for i=1:100
    for j=1:100
        a(i,j)=1;
    end
end
toc
disp('100*100按列遍历:')
tic
for j=1:100
    for i=1:100
        a(i,j)=1;
    end
end
toc
%500*500
disp('500*500按行遍历:')
tic
for i=1:500
    for j=1:500
        a(i,j)=1;
    end
end
toc
disp('500*500按列遍历:')
tic
for j=1:500
    for i=1:500
        a(i,j)=1;
    end
end
toc
%1000*1000
disp('1000*1000按行遍历:')
tic
for i=1:1000
    for j=1:1000
        a(i,j)=1;
    end
end
toc
disp('1000*1000按列遍历:')
tic
for j=1:1000
    for i=1:1000
        a(i,j)=1;
    end
end
toc
%2000*2000
disp('2000*2000按行遍历:')
tic
for i=1:2000
    for j=1:2000
        a(i,j)=1;
    end
end
toc
disp('2000*2000按列遍历:')
tic
for j=1:2000
    for i=1:2000
        a(i,j)=1;
    end
end
toc
%3000*3000
disp('3000*3000按行遍历:')
tic
for i=1:3000
    for j=1:3000
        a(i,j)=1;
    end
end
toc
disp('3000*3000按列遍历:')
tic
for j=1:3000
    for i=1:3000
        a(i,j)=1;
    end
end
toc
%4000*4000
disp('4000*4000按行遍历:')
tic
for i=1:4000
    for j=1:4000
        a(i,j)=1;
    end
end
toc
disp('4000*4000按列遍历:')
tic
for j=1:4000
    for i=1:4000
        a(i,j)=1;
    end
end
toc
%5000*5000
disp('5000*5000按行遍历:')
tic
for i=1:5000
    for j=1:5000
        a(i,j)=1;
    end
end
toc
disp('5000*5000按列遍历:')
tic
for j=1:5000
    for i=1:5000
        a(i,j)=1;
    end
end
toc
%6000*6000
disp('6000*6000按行遍历:')
tic
for i=1:6000
    for j=1:6000
        a(i,j)=1;
    end
end
toc
disp('6000*6000按列遍历:')
tic
for j=1:6000
    for i=1:6000
        a(i,j)=1;
    end
end
toc
%7000*7000
disp('7000*7000按行遍历:')
tic
for i=1:7000
    for j=1:7000
        a(i,j)=1;
    end
end
toc
disp('7000*7000按列遍历:')
tic
for j=1:7000
    for i=1:7000
        a(i,j)=1;
    end
end
toc
%8000*8000
disp('8000*8000按行遍历:')
tic
for i=1:8000
    for j=1:8000
        a(i,j)=1;
    end
end
toc
disp('8000*8000按列遍历:')
tic
for j=1:8000
    for i=1:8000
        a(i,j)=1;
    end
end
toc
%9000*9000
disp('9000*9000按行遍历:')
tic
for i=1:9000
    for j=1:9000
        a(i,j)=1;
    end
end
toc
disp('9000*9000按列遍历:')
tic
for j=1:9000
    for i=1:9000
        a(i,j)=1;
    end
end
toc
%10000*10000
disp('10000*10000按行遍历:')
tic
for i=1:10000
    for j=1:10000
        a(i,j)=1;
    end
end
toc
disp('10000*10000按列遍历:')
tic
for j=1:10000
    for i=1:10000
        a(i,j)=1;
    end
end
toc
%12000*12000
disp('12000*12000按行遍历:')
tic
for i=1:12000
    for j=1:12000
        a(i,j)=1;
    end
end
toc
disp('12000*12000按列遍历:')
tic
for j=1:12000
    for i=1:12000
        a(i,j)=1;
    end
end
toc
%14000*14000
disp('14000*14000按行遍历:')
tic
for i=1:14000
    for j=1:14000
        a(i,j)=1;
    end
end
toc
disp('14000*14000按列遍历:')
tic
for j=1:14000
    for i=1:14000
        a(i,j)=1;
    end
end
toc
%16000*16000
disp('16000*16000按行遍历:')
tic
for i=1:16000
    for j=1:16000
        a(i,j)=1;
    end
end
toc
disp('16000*16000按列遍历:')
tic
for j=1:16000
    for i=1:16000
        a(i,j)=1;
    end
end
toc
%18000*18000
disp('18000*18000按行遍历:')
tic
for i=1:18000
    for j=1:18000
        a(i,j)=1;
    end
end
toc
disp('18000*18000按列遍历:')
tic
for j=1:18000
    for i=1:18000
        a(i,j)=1;
    end
end
toc
%20000*20000
disp('20000*20000按行遍历:')
tic
for i=1:20000
    for j=1:20000
        a(i,j)=1;
    end
end
toc
disp('20000*20000按列遍历:')
tic
for j=1:20000
    for i=1:20000
        a(i,j)=1;
    end
end
toc

运行结果:

10*10按行遍历:
历时 0.001160 秒。
10*10按列遍历:
历时 0.002137 秒。

100*100按行遍历:
历时 0.002139 秒。
100*100按列遍历:
历时 0.001247 秒。

500*500按行遍历:
历时 0.005005 秒。
500*500按列遍历:
历时 0.002314 秒。

1000*1000按行遍历:
历时 0.013177 秒。
1000*1000按列遍历:
历时 0.008198 秒。

2000*2000按行遍历:
历时 0.055286 秒。
2000*2000按列遍历:
历时 0.031675 秒。

3000*3000按行遍历:
历时 0.111594 秒。
3000*3000按列遍历:
历时 0.054623 秒。

4000*4000按行遍历:
历时 0.159790 秒。
4000*4000按列遍历:
历时 0.031501 秒。

5000*5000按行遍历:
历时 0.253966 秒。
5000*5000按列遍历:
历时 0.040411 秒。

6000*6000按行遍历:
历时 0.347891 秒。
6000*6000按列遍历:
历时 0.051451 秒。

7000*7000按行遍历:
历时 0.474733 秒。
7000*7000按列遍历:
历时 0.065348 秒。

8000*8000按行遍历:
历时 0.614065 秒。
8000*8000按列遍历:
历时 0.082403 秒。

9000*9000按行遍历:
历时 0.748270 秒。
9000*9000按列遍历:
历时 0.101840 秒。

10000*10000按行遍历:
历时 0.951146 秒。
10000*10000按列遍历:
历时 0.126003 秒。

12000*12000按行遍历:
历时 1.470136 秒。
12000*12000按列遍历:
历时 0.201293 秒。

14000*14000按行遍历:
历时 1.947979 秒。
14000*14000按列遍历:
历时 0.222194 秒。

16000*16000按行遍历:
历时 2.618715 秒。
16000*16000按列遍历:
历时 0.296784 秒。

18000*18000按行遍历:
历时 5.445383 秒。
18000*18000按列遍历:
历时 2.052443 秒。

20000*20000按行遍历:
历时 7.020740 秒。
20000*20000按列遍历:
历时 2.864608 秒。

运行结果和C语言版本基本类似,只是按列遍历更优。注意到当数组大小增长(超过10000*10000)时,按行遍历的运行时间增长得更快,超过了C语言在相同大小数组的按列遍历运行时间。

一般来说,像C语言、C++、Java等语言,按行遍历要快于按列遍历(数组在内存中按行存储);像MATLAB、Fortran等语言,按列遍历要快于按行遍历(数组在内存中按列存储)。

猜你喜欢

转载自blog.csdn.net/upc122/article/details/108458646