ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【数据结构】数组与广义表

2021-01-23 12:01:49  阅读:209  来源: 互联网

标签:存储 数组 .. int 矩阵 三元组 广义 数据结构 data


二维数组压缩存储

普通二维数组

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

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

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

\[LOC(i,j)=LOC(0,0)+(n\times 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\),当\(i\ge 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("\ncpot:");
	for (i = 1; i <= M.nu; i++)printf("%d,", cpot[i]);
	printf("\n");
	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\n", 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\n", Q.m);
    printf("%d\n", Q.n);
    printf("%d\n", Q.t);
    for (int i = 1; i <= Q.t; i++)
    {
        printf("%d,%d,%d\n", Q.nodes[i].i, Q.nodes[i].j, Q.nodes[i].e);
    }
    return 0;
}

广义表的性质

  • 表头:广义表第一个元素(广义表非空)
  • 表尾:其余元素组成的(广义表非空),即除了第一个元素之外元素套括号。因此它必定是子表
  • 深度:广义表嵌套的括号层数

标签:存储,数组,..,int,矩阵,三元组,广义,数据结构,data
来源: https://www.cnblogs.com/fighterkaka22/p/14317124.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有