数据结构第五章 数组

1 数组定义与运算

数组的定义:

逻辑结构上,数组可以看做线性表的扩充。一维数组即为线性表,二维数组其数据元素为一维数组的线性表,以此类推,N维数组是数据元素为N-1维数组的线性表。

数组的运算:

  1. 获取特定位置的元素值
  2. 修改特定位置的元素值

2 数组的顺序存储与实现

对于数组而言,其维数和各维长度一旦确定,则该数组的元素个数就是确定的,并且数组的基本操作不涉及数组结构的变化,因此采用顺序存储更为合适。

数组的顺序存储结构有两种:

  1. 按行序存储
  2. 按列序存储

数组地址的计算方法(以按行序排序为例):

数组的地址计算公式
一维数组Loc(A[i]) = Loc(A[1]) + (i-1)*size
二维数组Loc(A[i][j]) = Loc(A[1][1]) + ((i-1)*n+j-1)*size
三维数组Loc(A[i][j][k]) = Loc(A[1][1][1]) + ((i-1)mn+(j-1)*n+k-1)*size

3 特殊矩阵的压缩存储

3.1 规律分布的特殊矩阵

3.1.1 三角矩阵

三角矩阵大体分为:下三角矩阵、上三角矩阵和对称矩阵。

下三角矩阵如图:
下三角矩阵
对于下三角矩阵,其元素分布为a11,a21.a22,a31,a32,a33……ann,共有1+2+……+n=n(n+1)/2个元素,因此我们可以把下三角矩阵存储到一个大小为n(n+1)/2的一维数组中,其中元素a[i][j]在数组C中的存储位置为:Loc[i,j] = Loc[1,1] + ((i -1)*i/2+j-1)*size

同样,对于上三角矩阵,也可以将其压缩存储到一个大小为n(n+1)/2的一维数组中。其中元素a[i][j]在数组C中的存储位置为:Loc[i,j]= Loc[1,1]+(j*(j -1)/2+ i-1)*size

对于对称矩阵,因其元素满足a[i][j]=a[j][i],我们可以为每一对相等的元素分配一个存储空间,即只存下三角(或上三角)矩阵,从而将n*n个元素压缩到n(n+1)/2个空间中。

3.1.2 带状矩阵

在矩阵A中,所有的非零元素都集中在以主对角线为中心的带状区域中。最常见的是三对角带状矩阵

带状矩阵

三对角带状矩阵特点:

  • 当i=1,j=1,2
  • 当i=n,j=n-1,n
  • 当1<i<n,j = i-1,i,i+1

三对角带状矩阵的压缩存储方法:

  1. 确定存储该矩阵所需的一维向量的大小:3*n-2
  2. 确定非零元素在一维数组空间中的地址:Loc(A[i][j]) = Loc(A[1][1]) + (3*(i-1)-1+j-i+1)size = Loc(A[1][1]) + (2(I-1)+j-1)*size

3.2 稀疏矩阵

指矩阵中大多数元素为零的矩阵。一般地,当非零元素个数只占矩阵元素总数的25%—30%,或低于这个百分数时,我们称这样的矩阵为稀疏矩阵。

3.2.1 稀疏矩阵的三元组表表示方法

在这里插入图片描述

#define MAXSIZE 255

typedef struct
{
    int row,col;  //非零元素的行值和列值
    int value;  //非零元素的值
}Triple;
typedef struct
{
    Triple data[MAXSIZE+1];  //data[0]未用
    int m,n,len;  //矩阵行数,列数和非零元素个数
}TSMatrix;

3.2.2 稀疏矩阵的转置

对于普通矩阵,我们只需要将其每个元素的行下标和列下标互换。但是对于用三元组表表示的稀疏矩阵,只把行下标和列下标互换是不够的。应归纳成以下三点:

  • 每个元素的行下标和列下标互换
  • 总行数m和总列数n互换
  • 重排三元组内各元素顺序,使转置后的三元组也按行(或列)为主序有规律的排列。

在这里插入图片描述
方法一:列序递增转置法

扫描A中所有col为1的元素,转置后添加至B。以此类推。

在这里插入图片描述
代码如下:

void TransposeTSMatrix(TSMatrix A, TSMatrix *B) {
    int i,j,k;
    B->m = A.n;
    B->n = A.m;
    B->len = A.len;
    if(B->len>0){
        j = 1;  //辅助计数器
        for(k=1;k<=A.n;k++){
            for(i=1;i<=A.len;i++)
            {
                if(A.data[i].col==k){
                    B->data[j].row = A.data[i].col;
                    B->data[j].col = A.data[i].row;
                    B->data[j].e = A.data[j].e;
                    j++;
                }
            }
        }
    }
}

方法二:一次定位快速转置法

设置两个数组num[]和position[],前者用来存放三元组表A第col列中非零元素总个数,后者存转置前三元组A第col列第一个非零元素在三元组表B中的存储位置(下标)

FastTransposeTSMatrix(TSMatrix A, TSMatrix * B){
    int col,t,p,q;
    B->len = A.len;
    B->n = A.m;
    B->m = A.n;
    if(B->len){
        for(col=1;col<=A.n;col++)
            num[col] = 0;
        for(t=1;t<=A.len;t++)
            num[A.data[t].col]++;  //采用数组下标计数法计算每一列非零元素个数
        position[1] = 1;
        
        for(col=2;col<=A.n;col++)
            position[col] = positon[col-1] + num[col-1]; //求col列第一个非零元素在B.data[]中的正确位置
        for(p=1;p<=A.len;p++){
            col = A.data[p].col;
            q = position[col];
            B->data[q].row = A.data[p].col;
            B->data[q].col = A.data[p].row;
            B->data[q].e = A.data[p].e;
            position[col]++;
        }    	
    }
}

4 实验题

在这里插入图片描述
在这里插入图片描述
列序递增算法代码:

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 100
//矩阵结构化描述
typedef struct{
    int row,col;  //非零元素的行值和列值
    int value;  //非零元素的值
}Triple;
typedef struct{
    Triple data[MAXSIZE+1];  //data[0]未用
    int m,n,len;  //矩阵行数,列数和非零元素个数
}TSMatrix;

//创建矩阵
void CreateTSMatrix(TSMatrix *A){
    int i = 1; //data[0]未用 i表示计数器
    printf("请输入矩阵的行数:");
    scanf("%d",&A->m);
    printf("请输入矩阵的列数:");
    scanf("%d",&A->n);
    printf("请输入矩阵元素(例如1,1,1):");
    while(1){
        scanf("%d,%d,%d", &A->data[i].row,&A->data[i].col,&A->data[i].value);
        if(A->data[i].row == 0 && A->data[i].col == 0 && A->data[i].value == 0)
            break;
        i++;
        A->len++;
    }
}
//稀释矩阵的转置的列序递增算法
void TransposeTSMatrix(TSMatrix A, TSMatrix *B) {
    int i,j,k;
    B->m = A.n;
    B->n = A.m;
    B->len = A.len;
    if(B->len>0){
        j = 1;  //辅助计数器
        for(k=1;k<=A.n;k++){
            for(i=1;i<=A.len;i++)
            {
                if(A.data[i].col==k){
                    B->data[j].row = A.data[i].col;
                    B->data[j].col = A.data[i].row;
                    B->data[j].value = A.data[i].value;
                    j++;
                }
            }
        }
    }
}
//矩阵打印
void printTSMatrix(TSMatrix *A){
    for(int i=1;i<=A->len;i++){
        printf("(%d,%d,%d)\n",A->data[i].row,A->data[i].col,A->data[i].value);
    }
}
//主函数
int main(){
    TSMatrix A;
    TSMatrix B;
    A.m = 0;
    A.n = 0;
    A.len = 0;
    CreateTSMatrix(&A);
    TransposeTSMatrix(A,&B);
    //打印原矩阵和新矩阵
    printf("原矩阵:\n");
    printTSMatrix(&A);
    printf("新矩阵:\n");
    printTSMatrix(&B);
    return 0;
}

结果如下:
在这里插入图片描述
快速转置法代码:

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 100

//矩阵结构化描述
typedef struct
{
    int row,col;  //非零元素的行值和列值
    int value;  //非零元素的值
}Triple;
typedef struct
{
    Triple data[MAXSIZE+1];  //data[0]未用
    int m,n,len;  //矩阵行数,列数和非零元素个数
}TSMatrix;

//创建矩阵
void CreateTSMatrix(TSMatrix *A){
    int i = 1; //data[0]未用 i表示计数器
    printf("请输入矩阵的行数:");
    scanf("%d",&A->m);
    printf("请输入矩阵的列数:");
    scanf("%d",&A->n);
    printf("请输入矩阵元素(例如1,1,1):");
    while(1){
        scanf("%d,%d,%d", &A->data[i].row,&A->data[i].col,&A->data[i].value);
        if(A->data[i].row == 0 && A->data[i].col == 0 && A->data[i].value == 0)
            break;
        i++;
        A->len++;
    }
}

//稀释矩阵的转置的快速转置方法
FastTransposeTSMatrix(TSMatrix A, TSMatrix *B){
    int col,t,p,q;
    int num[MAXSIZE],position[MAXSIZE];
    B->len = A.len;
    B->n = A.m;
    B->m = A.n;
    if(B->len){
        for(col=1;col<=A.n;col++)
            num[col] = 0;
        for(t=1;t<=A.len;t++)
            num[A.data[t].col]++;  //采用数组下标计数法计算每一列非零元素个数
        position[1] = 1;
        for(col=2;col<=A.n;col++)
            position[col] = position[col-1] + num[col-1]; //求col列第一个非零元素在B.data[]中的正确位置
        for(p=1;p<=A.len;p++){
            col = A.data[p].col;
            q = position[col];
            B->data[q].row = A.data[p].col;
            B->data[q].col = A.data[p].row;
            B->data[q].value = A.data[p].value;
            position[col]++;
        }    	
    }
}

//矩阵打印
void printTSMatrix(TSMatrix *A){
    for(int i=1;i<=A->len;i++){
        printf("(%d,%d,%d)\n",A->data[i].row,A->data[i].col,A->data[i].value);
    }
}

//主函数
int main(){
    TSMatrix A;
    TSMatrix B;
    A.m = 0;
    A.n = 0;
    A.len = 0;
    CreateTSMatrix(&A);
    FastTransposeTSMatrix(A,&B);
    //打印原矩阵和新矩阵
    printf("原矩阵:\n");
    printTSMatrix(&A);
    printf("新矩阵:\n");
    printTSMatrix(&B);
    return 0;
}

结果如下:
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值