5.1 数组的定义
- 在计算机科学中,数组数据结构(英语:array data structure),简称数组(英语:Array),是由相同类型的元素(element)的集合所组成的数据结构,分配一块连续的内存来存储。利用元素的索引(index)可以计算出该元素对应的存储地址
数组与线性表
- 相同之处:
它们都是若干个相同数据类型的数据元素a0,a1,a2,…,an-1,构成的有限序列 - 不同之处:
(1)数组要求其元素占用一块地址连续的内存单元空间,而线性表无此要求
(2)线性表的元素是逻辑意义上不可再分的元素,而数组中的每个元素还可以是一个数组
(3)数组的操作主要是向某个下标的数组元素中存放数据和取某个下标的数组元素,这与线性表的插入和删除操作不同
- 结论:线性表结构是数组结构的一个特例,而数组结构又是线性表结构的扩展
5.2 数组的顺序表示和实现
-
数组结构也可以使用两种存储结构,即顺序存储结构和链式存储结构
-
一维数组(n个元素)中任一元素ai的内存单元地址
- 一个m行n列的二维数组
注:C语言中数组元素采用行主序的存放方法,即行优先顺序
5.3 特殊矩阵和稀疏矩阵的存储
- 在计算机中,矩阵是一种常见的数据结构,用于表示二维的数值数组。计算机中的矩阵通常通过二维数组或列表的形式来表示,其中每个元素都可以通过其在矩阵中的行和列的索引进行访问
- 对称矩阵:对称矩阵是一种特殊的方阵,其主对角线上的元素对称地分布在矩阵的上下三角中。即,对称矩阵A的第i行第j列的元素等于其第j行第i列的元素,即A[i][j] = A[j][i],对称矩阵关于其主对角线是对称的
void compressSymmetricMatrix(int matrix[MAX_SIZE][MAX_SIZE], int n, int compressedArray[])
{
int k = 0;
for (int i = 0; i < n; i++)
{
compressedArray[k++] = matrix[i][i]; // 存储对角线上的元素
for (int j = i + 1; j < n; j++)
{
compressedArray[k++] = matrix[i][j]; // 存储上三角或下三角的元素
}
}
}
- 三角矩阵:三角矩阵是方形矩阵的一种,因其非零系数的排列呈三角形状而得名。三角矩阵分上三角矩阵和下三角矩阵两种。上三角矩阵的对角线左下方的系数全部为零,下三角矩阵的对角线右上方的系数全部为零。
void compressTriangularMatrix(int matrix[MAX_SIZE][MAX_SIZE], int n, int compressedArray[])
{
int k = 0;
for (int i = 0; i < n; i++)
{
compressedArray[k++] = matrix[i][i]; // 存储对角线元素
for (int j = i + 1; j < n; j++)
{
compressedArray[k++] = matrix[i][j]; // 存储上三角元素
}
}
}
- 对角矩阵:对角矩阵是一个主对角线之外的元素皆为0的矩阵,对角线上的元素可以为0或其他值
void compressDiagonalMatrix(int matrix[MAX_SIZE][MAX_SIZE], int n, int compressedArray[])
{
for (int i = 0; i < n; i++)
{
compressedArray[i] = matrix[i][i]; // 存储对角线元素
}
}
- 稀疏矩阵:稀疏矩阵是指在数值分析中,其元素大部分为零的矩阵
定义
// 三元组
typedef struct {
int i, j;
int e;
} Triple;
// 稀疏矩阵
typedef struct {
Triple data[MAXSIZE + 1];
int mu, nu, tu;
} Matrix;
打印
// 打印稀疏矩阵
void printMatrix(Matrix M) {
int i, j, k = 1;
for (i = 1; i <= M.mu; i++) {
for (j = 1; j <= M.nu; j++) {
// 判断是否为非零元素
if (i == M.data[k].i && j == M.data[k].j) {
printf("%d\t", M.data[k].e);
k++;
} else {
printf("0\t");
}
}
printf("\n");
}
}
转置
两种实现算法:
1.按列 col(1≤col≤M.nu)扫描三元表M.data,找出所有列号等于col的那些三元组,将它们的行号和列号互后依次放入T.data中 (跳着找,顺着存)
2. 先计算出M中每列第一个非零元素在T的三元表中的存储位置(用pot[]数组保存),然后按行扫描M的三元表的元素(顺着找,跳着存)
// 转置稀疏矩阵
void transionMatrix(Matrix M, Matrix *T) {
T->mu = M.nu;
T->nu = M.mu;
T->tu = M.tu;
if (T->tu) {
int q = 1;
// 遍历每一列
for (int col = 1; col <= M.nu; col++) {
for (int p = 1; p <= M.tu; p++) {
// 判断是否为非零元素
if (M.data[p].j == 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;
q++;
}
}
}
}
}
// 转置稀疏矩阵
void transionMatrix2(Matrix M, Matrix *T) {
T->mu = M.nu;
T->nu = M.mu;
T->tu = M.tu;
if (T->tu) {
int num[M.nu], cpot[M.nu];
int col, p, q;
// 初始化
for (col = 1; col <= M.nu; col++) {
num[col] = 0;
}
// 计算每一列的非零元素个数
for (p = 1; p <= M.tu; p++) {
num[M.data[p].j]++;
}
cpot[1] = 1;
// 计算每一列第一个非零元素在三元组表中的位置
for (col = 2; col <= M.nu; col++) {
cpot[col] = cpot[col - 1] + num[col - 1];
}
// 转置
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]++;
}
}
}
5.4 广义表
- 广义表是一种非线性的数据结构,它可以包含原子和子表。如果广义表的每个元素都是原子,它就变成了线性表,它由n ( ≥0 )个表元素组成的有限序列,记作LS = (a0, a1, a2, …, an-1) LS是表名,ai是表元素,它可以是表 (称为子表),可以是数据。广义表的元素可以是子表,而子表的元素还可以是子表
- 由于广义表(a1,a2,a3,…an)中的数据元素可以具有不同的结构,(或是原子,或是广义表),因
此,难以用顺序存储结构表示,通常采用链式存储结构,每个数据元素可用一个结点表示
两种链式存储方法
1:头尾链表表示法
2:扩展线性链表表示法
定义
typedef struct GLNode {
int tag;
union {
ElemType data;
struct {
struct GLNode *hp, *tp;
} ptr;
} u;
} * GList;
创建
void CreateGList(GList *L) {
char c;
scanf("%c", &c);
if (c == '#') {
*L = NULL;
} else if (c == '(') {
*L = (GList) malloc(sizeof(struct GLNode));
(*L)->tag = 1;
CreateGList(&((*L)->u.ptr.hp));
CreateGList(&((*L)->u.ptr.tp));
} else {
*L = (GList) malloc(sizeof(struct GLNode));
(*L)->tag = 0;
(*L)->u.data = c;
CreateGList(&((*L)->u.ptr.tp));
}
}
完整代码
1.对称矩阵
#include <stdio.h>
#define MAX_SIZE 100
void compressSymmetricMatrix(int matrix[MAX_SIZE][MAX_SIZE], int n, int compressedArray[])
{
int k = 0;
for (int i = 0; i < n; i++)
{
compressedArray[k++] = matrix[i][i]; // 存储对角线上的元素
for (int j = i + 1; j < n; j++)
{
compressedArray[k++] = matrix[i][j]; // 存储上三角或下三角的元素
}
}
}
void decompressSymmetricMatrix(int compressedArray[], int n, int matrix[MAX_SIZE][MAX_SIZE])
{
int k = 0;
for (int i = 0; i < n; i++)
{
matrix[i][i] = compressedArray[k++]; // 恢复对角线上的元素
for (int j = i + 1; j < n; j++)
{
matrix[i][j] = compressedArray[k]; // 恢复上三角或下三角的元素
matrix[j][i] = compressedArray[k++]; // 对称性质,填充对应位置的元素
}
}
}
int main()
{
int n; // 矩阵的大小
int matrix[MAX_SIZE][MAX_SIZE]; // 原始对称矩阵
int compressedArray[MAX_SIZE * (MAX_SIZE + 1) / 2]; // 压缩后的数组
printf("请输入对称矩阵的大小:");
scanf("%d", &n);
printf("请输入对称矩阵的元素:\n");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
scanf("%d", &matrix[i][j]);
}
}
compressSymmetricMatrix(matrix, n, compressedArray);
printf("压缩后的数组为:\n");
for (int i = 0; i < n * (n + 1) / 2; i++)
{
printf("%d ", compressedArray[i]);
}
printf("\n");
int decompressedMatrix[MAX_SIZE][MAX_SIZE]; // 解压缩后的矩阵
decompressSymmetricMatrix(compressedArray, n, decompressedMatrix);
printf("解压缩后的矩阵为:\n");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d ", decompressedMatrix[i][j]);
}
printf("\n");
}
return 0;
}
2.三角矩阵
#include <stdio.h>
#define MAX_SIZE 100
void compressTriangularMatrix(int matrix[MAX_SIZE][MAX_SIZE], int n, int compressedArray[])
{
int k = 0;
for (int i = 0; i < n; i++)
{
compressedArray[k++] = matrix[i][i]; // 存储对角线元素
for (int j = i + 1; j < n; j++)
{
compressedArray[k++] = matrix[i][j]; // 存储上三角元素
}
}
}
void decompressTriangularMatrix(int compressedArray[], int n, int matrix[MAX_SIZE][MAX_SIZE])
{
int k = 0;
for (int i = 0; i < n; i++)
{
matrix[i][i] = compressedArray[k++]; // 恢复对角线元素
for (int j = i + 1; j < n; j++)
{
matrix[i][j] = compressedArray[k++]; // 恢复上三角元素
matrix[j][i] = 0; // 填充对称位置的元素为零
}
}
}
int main()
{
int n; // 矩阵的大小
int matrix[MAX_SIZE][MAX_SIZE]; // 原始矩阵
int compressedArray[MAX_SIZE * (MAX_SIZE + 1) / 2]; // 压缩后的数组
printf("请输入三角矩阵的大小:");
scanf("%d", &n);
printf("请输入三角矩阵的元素:\n");
for (int i = 0; i < n; i++)
{
for (int j = i; j < n; j++)
{
scanf("%d", &matrix[i][j]);
}
}
compressTriangularMatrix(matrix, n, compressedArray);
printf("压缩后的数组为:\n");
for (int i = 0; i < n * (n + 1) / 2; i++)
{
printf("%d ", compressedArray[i]);
}
printf("\n");
int decompressedMatrix[MAX_SIZE][MAX_SIZE]; // 解压缩后的矩阵
decompressTriangularMatrix(compressedArray, n, decompressedMatrix);
printf("解压缩后的矩阵为:\n");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d ", decompressedMatrix[i][j]);
}
printf("\n");
}
return 0;
}
3.对角矩阵
#include <stdio.h>
#define MAX_SIZE 100
void compressDiagonalMatrix(int matrix[MAX_SIZE][MAX_SIZE], int n, int compressedArray[])
{
for (int i = 0; i < n; i++)
{
compressedArray[i] = matrix[i][i]; // 存储对角线元素
}
}
void decompressDiagonalMatrix(int compressedArray[], int n, int matrix[MAX_SIZE][MAX_SIZE])
{
for (int i = 0; i < n; i++)
{
matrix[i][i] = compressedArray[i]; // 恢复对角线元素
}
}
int main()
{
int n; // 矩阵的大小
int matrix[MAX_SIZE][MAX_SIZE]; // 原始矩阵
int compressedArray[MAX_SIZE]; // 压缩后的数组
printf("请输入对角矩阵的大小:");
scanf("%d", &n);
printf("请输入对角矩阵的元素:\n");
for (int i = 0; i < n; i++)
{
scanf("%d", &matrix[i][i]);
}
compressDiagonalMatrix(matrix, n, compressedArray);
printf("压缩后的数组为:\n");
for (int i = 0; i < n; i++)
{
printf("%d ", compressedArray[i]);
}
printf("\n");
int decompressedMatrix[MAX_SIZE][MAX_SIZE]; // 解压缩后的矩阵
decompressDiagonalMatrix(compressedArray, n, decompressedMatrix);
printf("解压缩后的矩阵为:\n");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i == j)
{
printf("%d ", decompressedMatrix[i][j]);
}
else
{
printf("0 ");
}
}
printf("\n");
}
return 0;
}
4.广义表
#include <stdio.h>
#include <stdlib.h>
#define ElemType int
typedef struct GLNode {
int tag; // 标志域,0表示原子,1表示子表
union {
ElemType data; // 原子结点的值域
struct {
struct GLNode *hp, *tp; // 指向表头和表尾的指针域
} ptr; // 子表结点的指针域
} u;
} * GList;
void CreateGList(GList *L) { // 创建广义表
char c;
scanf("%c", &c);
if (c == '#') { // 空表
*L = NULL;
} else if (c == '(') { // 子表
*L = (GList) malloc(sizeof(struct GLNode));
(*L)->tag = 1;
CreateGList(&((*L)->u.ptr.hp)); // 递归创建子表的表头
CreateGList(&((*L)->u.ptr.tp)); // 递归创建子表的表尾
} else { // 原子
*L = (GList) malloc(sizeof(struct GLNode));
(*L)->tag = 0;
(*L)->u.data = c;
CreateGList(&((*L)->u.ptr.tp)); // 递归创建原子后面的元素
}
}
void PrintGList(GList L) { // 打印广义表
if (L == NULL) { // 空表
printf("#");
} else if (L->tag == 0) { // 原子结点
printf("%c", L->u.data);
PrintGList(L->u.ptr.tp); // 递归打印原子后面的元素
} else { // 子表结点
printf("(");
PrintGList(L->u.ptr.hp); // 递归打印子表的表头
printf(",");
PrintGList(L->u.ptr.tp); // 递归打印子表的表尾
printf(")");
}
}
int main() {
GList L;
CreateGList(&L);
PrintGList(L);
return 0;
}