zoukankan      html  css  js  c++  java
  • 学好数据结构和算法 —— 非线性结构(上)

    序言

    上篇讲到线性结构,和线性结构相反的是非线性结构,非线性结构特点是一个结点元素可能有多个直接前驱和多个直接后继。常见的非线性结构有:二(多)维数组、树、图。

    本来计划是非线性结构作为一篇,写着写着发现内容确实太多了,拆分为上、中、下3篇比较合适,所以改变了之前的计划。

    1、二维数组

    如:a[0][0]在水平方向有后继a[0][1],垂直方向有后继a[1][0],二维数组从水平方向或垂直方向看,某个元素都有前驱或后继,并不是线性结构。

    二维数组的表示方法

    矩阵表示法

    行向量表示法

    列向量表示法

    二维数组的两种存储方式

    其中行向量和列向量表示法分别对应二维数组的行序为主序和列序为主序两种存储方式。对于任意一个二维数组amxn

    行序为主序储存时,任意一个元素a[i][j]寻址公式为:

    &a[i][j] = &a[0][0] + (i * n + j) * data_size

    其中:

      &a[i][j] : 为元素a[i][j]的地址

      &a[0][0]:为a[0][0]的存储位置(即数组的起始位置)

      data_size:数组里储存元素的长度

    行序为主序储存时,任意一个元素a[i][j]寻址公式为:

    &a[i][j] = &a[0][0] + (j * m + i) * data_size

    公式参数参考列序存储公式参数说明。

    2、三(多)维数组

    相对于二维数组来说,三维以及N(N>2)维数组对于很多人来说可能不太熟悉,因为日常开发中用的比较少。对于三维数组可以放到坐标系里类比,有了3个维度,如下图所示:

    分不了行和列了,其实返回去再看看二维数组,行为主序存储方式和列为主序存储方式其实分别对应的就是以左下标作为主序存储方式和以右下标作为主序存储方式。对于三(多)维数组来说也只有两种存储方式:以左下标作为主序存储方式和以右下标作为主序存储方式。

    按左下标作为主序存储

    任意一个N(n>2)维数组A[i1][i2]…[in],按左下标作为主序存储时候,设A' = A[i1][i2]…[in-1],那么A[i1][i2]…[in]可以简化为A'[0],A'[1],A'[2],…,A'[in - 1],然后存储A'时候,也用左下标优先方式转化为A''[0],A''[1],A''[2],…,A''[in-1 - 1],依次类推,当存储最后1维数组时为A[0][i2]…[in],A[1][i2]…[in],A[2][i2]…[in],…A[i1 - 1][i2]…[in],这样就完成了N维数组的存储。

    给定一个A[k1][k2]…[kn]元素,求它在数组中存储的位置可以依据公式:

    对于三维数组A[x][y][z]来说,当以左下标优先存储时候,元素A[1][2][3]地址代入公式计算:

    &A[1][2][3] = &A[0][0][0] + (3 + 2 * z + 1 * y * z) * data_size

    为了便于理解,三维数组a[3][4][5]左下标优先存储示例: 

    左下标优先存储:
        a[0][0][0]    a[0][0][1]    a[0][0][2]    a[0][0][3]    a[0][0][4]    a[0][1][0]    a[0][1][1]    a[0][1][2]    a[0][1][3]    a[0][1][4]
        a[0][2][0]    a[0][2][1]    a[0][2][2]    a[0][2][3]    a[0][2][4]    a[0][3][0]    a[0][3][1]    a[0][3][2]    a[0][3][3]    a[0][3][4]
        a[1][0][0]    a[1][0][1]    a[1][0][2]    a[1][0][3]    a[1][0][4]    a[1][1][0]    a[1][1][1]    a[1][1][2]    a[1][1][3]    a[1][1][4]
        a[1][2][0]    a[1][2][1]    a[1][2][2]    a[1][2][3]    a[1][2][4]    a[1][3][0]    a[1][3][1]    a[1][3][2]    a[1][3][3]    a[1][3][4]
        a[2][0][0]    a[2][0][1]    a[2][0][2]    a[2][0][3]    a[2][0][4]    a[2][1][0]    a[2][1][1]    a[2][1][2]    a[2][1][3]    a[2][1][4]
        a[2][2][0]    a[2][2][1]    a[2][2][2]    a[2][2][3]    a[2][2][4]    a[2][3][0]    a[2][3][1]    a[2][3][2]    a[2][3][3]    a[2][3][4]

    按右下标作为主序存储

    任意一个N(n>2)维数组A[i1][i2]…[in],按右下标作为主序存储时候,设A' = A[i2]…[in-1][in],那么A[i1][i2]…[in]可以简化为A'[0],A'[1],A'[2],…,A'[i1 - 1],然后存储A'时候,也用右下标优先方式转化为A''[0],A''[1],A''[2],…,A''[i2 - 1],依次类推,当存储第n维数组时为A[i1][i2]…[in-1][0],A[i1][i2]…[in-1][1],A[i1][i2]…[in-1][in - 1],这样就完成了N维数组的存储。

    给定一个A[k1][k2]…[kn]元素,求它在数组中存储的位置可以依据公式:

    对于三维数组A[x][y][z]来说,当以右下标优先存储时候,元素A[1][2][3]地址代入公式计算:

    &A[1][2][3] = &A[0][0][0] + (1 + 2 * x + 3 * x * y) * data_size

    为了便于理解,三维数组a[3][4][5]右下标优先存储示例:

    右下标优先存储:
        a[0][0][0]    a[1][0][0]    a[2][0][0]    a[0][1][0]    a[1][1][0]    a[2][1][0]    a[0][2][0]    a[1][2][0]    a[2][2][0]    a[0][3][0]
        a[1][3][0]    a[2][3][0]    a[0][0][1]    a[1][0][1]    a[2][0][1]    a[0][1][1]    a[1][1][1]    a[2][1][1]    a[0][2][1]    a[1][2][1]
        a[2][2][1]    a[0][3][1]    a[1][3][1]    a[2][3][1]    a[0][0][2]    a[1][0][2]    a[2][0][2]    a[0][1][2]    a[1][1][2]    a[2][1][2]
        a[0][2][2]    a[1][2][2]    a[2][2][2]    a[0][3][2]    a[1][3][2]    a[2][3][2]    a[0][0][3]    a[1][0][3]    a[2][0][3]    a[0][1][3]
        a[1][1][3]    a[2][1][3]    a[0][2][3]    a[1][2][3]    a[2][2][3]    a[0][3][3]    a[1][3][3]    a[2][3][3]    a[0][0][4]    a[1][0][4]
        a[2][0][4]    a[0][1][4]    a[1][1][4]    a[2][1][4]    a[0][2][4]    a[1][2][4]    a[2][2][4]    a[0][3][4]    a[1][3][4]    a[2][3][4]
  • 相关阅读:
    Java实现 LeetCode 69 x的平方根
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 66 加一
    Java实现 LeetCode 66 加一
    CxSkinButton按钮皮肤类
  • 原文地址:https://www.cnblogs.com/mr-yang-localhost/p/9977910.html
Copyright © 2011-2022 走看看