您的位置 首页 编程语言

zigzag扫描简介

1.什么是zigzag扫描

zigzag扫描是在图像处理里边使用的,比如采样、变换、量化、编码,在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan)。给定一个n×n的矩阵,Z字形扫描的过程如下图所示:

 

 

2.zigzag扫描的基本原理

 

用一个符号值或串长代替具有相同值的连续符号(连续符号构成了一段连续的“行程”。行程编码因此而得名),使符号长度少于原始数据的长度。 例如:5555557777733322221llllll

行程编码为:(5,6)(7,5)(3,3)(2,4)(l,7)。可见,行程编码的位数远远少于原始字符串的位数。

 

3.z字型扫描矩阵例题

对于下面的4×4的矩阵,
1 5 3 9
3 7 5 6
9 4 6 4
7 3 1 3
对其进行Z字形扫描后得到长度为16的序列:
1 5 3 9 7 3 9 5 4 7 3 6 6 4 1 3
请实现一个Z字形扫描的程序,给定一个n×n的矩阵,输出对这个矩阵进行Z字形扫描的结果。
输入格式
输入的第一行包含一个整数n,表示矩阵的大小。
输入的第二行到第n+1行每行包含n个正整数,由空格分隔,表示给定的矩阵。
输出格式
输出一行,包含n×n个整数,由空格分隔,表示输入的矩阵经过Z字形扫描后的结果。
样例输入
4
1 5 3 9
3 7 5 6
9 4 6 4
7 3 1 3
样例输出
1 5 3 9 7 3 9 5 4 7 3 6 6 4 1 3
评测用例规模与约定
1≤n≤500,矩阵元素为不超过1000的正整数。

 

4 . z字型扫描矩阵例题解法:

 

扫描输出有四种状态,每次输出要判定下一次的行走路线,走一步就输出一个。

四种状态为{right,leftDown,down,rightUp}。

开始我还怀疑,Z字形扫描矩阵是否能够遍历矩阵所有的元素。下面我们来分析一下:

1、前提是这个矩阵是一个n维方阵,假设为Anxn.

2、从输出当前的元素A[i][j],并根据当前的状态来判断下一步的扫描状态。该如何判断呢?可以发现每次在执行完当前状态后,行号i或者列号j都有可能发生改变,那么就可以结合当前状态和行,列号的取值来判定下一步的行走路线。

从上图中我们可以发现:

right状态始终在首行或者尾行上执行,并且执行right状态后列号j会增加1,即j = j+1。所以我们可以根据当前状态的下一步状态有两种:

当i == 0时,state = leftDown;

当i == n-1时,state = rightUp。

执行完leftDown状态后,i = i+1,j = j-1,其下一步状态有三种:

当 j == 0 && i != n-1时,state = down;

当 row == n-1时,state = right;

其它情况,state = leftDown(自身状态)。

对于rightUp和down状态,其分析方法和上面两种类似,就不再做分析。

综合上面分析来看,状态每次要发生改变的话,行号或者列号必须处于临界状态,即它们的取值为{0,n-1}。

 

5.z字型扫描矩阵代码

#include <iostream>

using namespace std;

int A[501][501];
enum  Choice
{
    rightTowards,//向移动
    rightUp,//向右上移动
    down,//向下移动
    leftDown//向左下移动
};

void zigzagScan(int n)
{
    for (int i = 0; i < n; ++i)
    for (int j = 0; j < n; ++j)
        cin >> A[i][j];
    int row = 0, col = 0;
    Choice choice = rightTowards;
    //row = n-1&&col = n-1的情况在while循环结束后处理,防止出现越界的情况
    while (row != n - 1 || col != n - 1)
    {
        cout << A[row][col] << ' ';
        switch (choice)
        {
        case rightTowards:
            col++;
            if (row == 0)
                choice = leftDown;
            else
                choice = rightUp;
            break;
        case rightUp:
            row--;
            col++;
            if (row == 0 && col != n - 1)
                choice = rightTowards;
            else if (col == n - 1)
                choice = down;
            else
                choice = rightUp;
            break;
        case down:
            row++;
            if (col == 0)
                choice = rightUp;
            else
                choice = leftDown;
            break;
        case leftDown:
            row++;
            col--;
            if (col == 0 && row != n - 1)
                choice = down;
            else if (row == n - 1)
                choice = rightTowards;
            else
                choice = leftDown;
            break;
        }
    }
    cout << A[n - 1][n - 1];
}

void main(void)
{
    int n;
    while (cin >> n)
    {
        zigzagScan(n);
    }
}

猫叔总结了 适合新手操作的副业 《淘宝虚拟产品月入2万的 6个 细分类目》的电子书 仅供参考

如果你对虚拟产品比较感兴趣,可以点击:

淘宝卖什么虚拟产品赚钱(月入2万+)

hadoopall

关于花猫大叔短视频创业 作者: hadoopall

热门文章

发表评论

电子邮件地址不会被公开。