zoukankan      html  css  js  c++  java
  • 【数据结构】数组与广义表

    二维数组压缩存储

    普通二维数组

    二维数组有两种存储方式:

    • 以列序为主序的存储方式,就是把每一列拼接起来
    • 以行序为主序的存储方式,就是把每一行拼接起来

    假设每个数据元素占L个存储单元,则二维数组A任意元素的存储位置:(如果是从1开始,i,j都减一)

    [LOC(i,j)=LOC(0,0)+(n imes i+j)L ]

    普通对称矩阵

    对于对称矩阵,我们可以为每一对对称元分配一个存储空间,则可以将(n^2)个元压缩存储到(n(n+1)/2)个元的空间中。

    (sa[n(n+1)/2])作为n阶对称矩阵A的存储结构,则(sa[k])和矩阵元素(a_{ij})之间存在一一对应的关系:(从下标0开始存储)

    (k=frac{i(i-1)}{2}+j-1),当(ige j)

    (k=frac{j(j-1)}{2}+i-1),当(i<j)

    三对角矩阵

    将A[1..n][1..n]压缩至B[0..3n-3]时,aij与bk的对应关系为:k=2i+j-3;

    将A[1..n][1..n]压缩至B[1..3n-2]时,aij与bk的对应关系为:k=2i+j-2;

    稀疏矩阵

    利用三元组(i,j,k)分别对应矩阵非零元的行、列、数据。

    稀疏矩阵转置

    原理:

    (1)将a,b矩阵行列值进行交换;

    (2)将每个元组中i,j交换;

    (3)重排三元组间顺序;

    方法:

    (1)按照b.data中三元组的次序依次在a.data找到相应的三元组进行转置。

    (2)按照a.data中三元组的次序进行转置,并将转置后的三元组置于b中恰当的位置。

    #include<iostream>
    #define MAX 100
    using namespace std;
    typedef struct {
    	int i, j, e;
    }list;
    typedef struct {
    	list data[MAX];
    	int mu, nu, tu;
    }TS;
    
    int main()
    {
    	TS M, T;
    	int num[MAX], cpot[MAX];
    	int i, t, p, q, col;
    	cin >> M.mu >> M.nu >> M.tu;
    	for (i = 0; i < 100; i++)num[i] = 0;
    	for (i = 1; i <= M.tu; i++)cin >> M.data[i].i >> M.data[i].j >> M.data[i].e;
    	for (t = 1; t <= M.tu; ++t)++num[M.data[t].j];
    	cpot[1] = 1;
    	for (col = 2; col <= M.nu; col++)cpot[col] = cpot[col - 1] + num[col - 1];
    	printf("num:");
    	for (i = 1; i <= M.nu; i++)printf("%d,", num[i]);
    	printf("
    cpot:");
    	for (i = 1; i <= M.nu; i++)printf("%d,", cpot[i]);
    	printf("
    ");
    	for (p = 1; p <= M.tu; ++p) {
    		col = M.data[p].j;
    		q = cpot[col];
    		T.data[q].i = M.data[p].j;
    		T.data[q].j = M.data[p].i;
    		T.data[q].e = M.data[p].e;
    		cpot[col]++;
    	}
    	for (i = 1; i <= M.tu; i++)printf("%d,%d,%d
    ", T.data[i].i, T.data[i].j, T.data[i].e);
    	return 0;
    }
    

    稀疏矩阵乘积

    #include<stdio.h>
    typedef struct
    {
        int i, j;
        int e;
    } Node;
    typedef struct
    {
        Node nodes[105];
        int rpos[105];//各行第一个非零元的位置表
        int m, n, t;
    } Matrix;
    int main()
    {
        //freopen("/Users/zhj/Downloads/test.txt", "r", stdin);
        Matrix A, B;
        scanf("%d%d%d", &A.m, &A.n, &A.t);
        for (int i = 1; i <= A.t; i++)
        {
            scanf("%d%d%d", &A.nodes[i].i, &A.nodes[i].j, &A.nodes[i].e);
        }
        int num[1000];
        for (int col = 1; col <= A.m; col++)
        {
            num[col] = 0;
        }
        for (int i = 1; i <= A.t; i++)
        {
            num[A.nodes[i].i]++;
        }
        A.rpos[1] = 1;
        for (int col = 2; col <= A.m; col++)
        {
            A.rpos[col] = A.rpos[col - 1] + num[col - 1];
        }
        scanf("%d%d%d", &B.m, &B.n, &B.t);
        for (int i = 1; i <= B.t; i++)
        {
            scanf("%d%d%d", &B.nodes[i].i, &B.nodes[i].j, &B.nodes[i].e);
        }
        for (int col = 1; col <= B.m; col++)
        {
            num[col] = 0;
        }
        for (int i = 1; i <= B.t; i++)
        {
            num[B.nodes[i].i]++;
        }
        B.rpos[1] = 1;
        for (int col = 2; col <= B.m; col++)
        {
            B.rpos[col] = B.rpos[col - 1] + num[col - 1];
        }
        Matrix Q;
        Q.m = A.m;
        Q.n = B.n;
        Q.t = 0;//创建答案矩阵
        if (A.t * B.t != 0)
        {//Q是非零矩阵
            for (int arow = 1; arow <= A.m; arow++)
            {//处理A的每一行
                int ctemp[105] = {0};
                Q.rpos[arow] = Q.t + 1;
                int tp;//tp是下一行元素在nodes表中位置
                if (arow < A.m)
                {
                    tp = A.rpos[arow + 1];
                }
                else
                {
                    tp = A.t + 1;
                }
                for (int p = A.rpos[arow]; p < tp; p++)
                {//对当前行中每一个非零元,既从当前在nodes表中位置找到下一行元素在nodes表的位置
                    int brow = A.nodes[p].j;//此为A表中的纵向位置值,在B表中找相应的行号即可
                    int t;//t仍然为下一行的位置
                    if (brow < B.m)
                    {
                        t = B.rpos[brow + 1];
                    }
                    else
                    {
                        t = B.t + 1;
                    }
                    for (int q = B.rpos[brow]; q < t; q++)
                    {
                        int ccol = B.nodes[q].j;//Q中的纵坐标是以B元素中的j来说话的
                        ctemp[ccol] += A.nodes[p].e * B.nodes[q].e;
                    }
                }
                for (int ccol = 1; ccol <= Q.n; ccol++)
                {//压缩存储该行的非零元
                    if (ctemp[ccol])
                    {//如果此处有值的话
                        Q.t++;//Q的非零元素多了一个
                        Q.nodes[Q.t].i = arow;//行号为此时遍历的A的行号
                        Q.nodes[Q.t].j = ccol;//列号为此时正在进行压缩所遍历到有值的地方
                        Q.nodes[Q.t].e = ctemp[ccol];//累计的和拷贝过来
                    }
                }
            }
        }
        printf("%d
    ", Q.m);
        printf("%d
    ", Q.n);
        printf("%d
    ", Q.t);
        for (int i = 1; i <= Q.t; i++)
        {
            printf("%d,%d,%d
    ", Q.nodes[i].i, Q.nodes[i].j, Q.nodes[i].e);
        }
        return 0;
    }
    

    广义表的性质

    • 表头:广义表第一个元素(广义表非空)
    • 表尾:其余元素组成的(广义表非空),即除了第一个元素之外元素套括号。因此它必定是子表
    • 深度:广义表嵌套的括号层数
  • 相关阅读:
    网络中常用的各种协议(针对TCP/IP协议组)
    报错注入小技巧
    2017swpu-ctf总结
    2017EIS高校运维大赛ctf wirteup
    discuz 3.x ssrf分析
    ssrf漏洞分析
    xxe漏洞分析
    phpcms9.6 注入分析
    74cms漏洞分析
    关于npm
  • 原文地址:https://www.cnblogs.com/fighterkaka22/p/14317124.html
Copyright © 2011-2022 走看看