数组是一种常用的数据结构。高级程序设计评议都提供了支持数组的基本方法。数组分静态数组和动态数组。静态数组和动态数组的实现机制相似,只是在程序设计时向系统申请内在空间的时间不同。
数组
数组是n(n>1)个相同数据类型的数据元素a0,a1,a2,…,a(n-1)构成的占用一块地址连续的内存单元有限序列。
数据集合:
数据的数据集合可以表示为a0,a1,a2,…,a(n-1),每个数据元素的数据类型为抽象数据元素类型DataType。
操作集合:
(1).求数组元素个数ArrayLength(D):函数返回数组D的元素个数。
(2).存数组元素Storage(D,i,x):把数据元素x存入下标为i的数组D中,其约束条件为0<=i<=ArrayLength(D) – 1.
(3).取数组元素Get(D,i,x):取出下标为i的数组D中的元素赋给参数x,其约束条件为0<=i<=ArrayLength(D)-1
动态数组
数组有静态数组和动态数组两种,静态数组在定义时就必须给出数组个数,因为编译系统要在软件编译时就为静态数组分配内存空间。动态数组是在需要存储单元空间时才给出数组的具体个数。高级程序设计语言一般都提供支持用户定义动态数组的函数或运算符。
C语言提供建立和撤消动态数组的函数malloc()函数,calloc()函数,free()函数
例1:
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
void main(void)
{
int *a,n = 10,i;
//动态申请n个int类型的内存空间,若内存空间不足则退出
if((a = (int*)malloc(n*sizeof(int))) == NULL)
{
printf("系统内存空间不足!");
exit(0);
}
for(i = 0;i < n; i++)
{
a[i] = i + 1;
}
for(i = 0;i < n; i++)
{
printf("%d ",a[i]);
}
printf("\n");
free(a);
}
例2:
定义有3行,4列整数类型的二维数组a,先逐行分别给数组元素赋数据1,2,…,12,然后显示数组中的数值。要求分别把申请二维动态数组的过程和释放二维动态数组的过程编写成函数。
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
//函数返回动态申请的row行,col列的二维动态数组,内存不足时退出
int ** Make2DArray(int row,int col)
{
int **a,i;
//动态申请 row个int指针类型的内存空间,内存不足时退出
if((a = (int**)malloc(row*sizeof(int*))) == NULL)
{
printf("系统内存空间不足!");
exit(0);
}
for(i = 0;i < row; i++)
{
if((a[i] = (int*)malloc(col*sizeof(int))) == NULL)
{
//动态申请col个int类型的内存空间,内存不足时退出
printf("系统内存空间不足!");
exit(0);
}
}
return a;
}
//释放二维 动态数组a的存储空间,row为数组行数
void Diliver2DArray(int**a,int row)
{
int i;
for(i = 0;i < row; i++)
free(a[i]);
free(a);
}
void main(void)
{
int i,j,c;
int row = 3,col = 4,**a;
a = Make2DArray(row,col);
c = 1;
for(i = 0;i < row; i++)
{
for(j = 0;j < col; j++)
{
a[i][j] = c;
c++;
}
}
for(i = 0;i < row; i++)
{
for(j = 0;j < col; j++)
{
printf("%d\t",a[i][j]);
}
printf("\n");
}
Diliver2DArray(a,row);
}
稀疏矩阵的压宿存储
用顺序表存储的三元组线性表称作三元组顺序表。三元组顺序表是把三元组定义成顺序表的数据元素。因此,可把三元组定义成顺序表的数据元素:
typedef struct {
DataType list[MaxSize];
int size;
}SeqList;
//顺序表操作实现
//1.初始化
void ListInitiate(SeqList*L)
{
L->size = 0;//定义初始数据元素个数
}
//2.求当前数据元素个数
int ListLength(SeqList L)
{
return L.size;//返回顺序表L的当前数据元素个数
}
//3.插入数据元素
int ListInsert(SeqList*L,int i,DataType x)
{
/*
在顺序表L的第i(0<=i<=size)个位置前插入数据元素值x
插入成功返回1,插入失败返回0
*/
int j;
if(L->size >= MaxSize)
{
printf("顺序表已满无法插入!\n");
return 0;
}
else if(i < 0 || i > L->size)
{
printf("参数i不合法!\n");
return 0;
}
else
{
/*为插入做准备*/
for(j=L->size;j > i; j--)
{
L->list[j] = L->list[j-1];
}
L->list[i] = x; /*插入元素x*/
L->size++; /*元素个数加1*/
return 1;
}
}
//4.删除数据元素
int ListDelete(SeqList*L,int i,DataType*x)
{
/*
删除顺序表L中位置为i(0<=i<=size-1)的数据元素并存放到x中
删除成功返回1,删除失败返回0
*/
int j;
if(L->size <= 0)
{
printf("顺序表已空无数据元素可删!\n");
return 0;
}
else if(i < 0 || i > L->size - 1)
{
printf("参数i不合法\n");
return 0;
}
else
{
*x = L->list[i]; /* 保存删除的元素到x中*/
for(j = i;j < L->size-1; j++)
{
L->list[j] = L->list[j+1];
}
L->size--; /*数据元素个数减1*/
return 1;
}
}
//5.取数据元素
int ListGet(SeqList L,int i,DataType* x)
{
/* 取顺序表L中第i个数据元素存于x中,成功返回1,失败返回0*/
if(i < 0 || i > L.size - 1)
{
printf("参数i不合法!\n");
return 0;
}
else
{
*x=L.list[i];
return 1;
}
}
#include <stdio.h>
#define MaxSize 1000
typedef int elemtype;
typedef struct
{
int i; //行号
int j; //列号
elemtype d; //元素值
} DataType;
typedef struct
{
int md; //行数
int nd; //列数
int td; //非零元素个数
} TriType;
#include "SeqList.h"
/*
a为转置前的三元组顺序表,da是a的控制数据
三元组顺序表a按先行序后列序的顺序存放
*/
void Transition1(SeqList a,TriType da,SeqList *b,TriType*db)
{
int p;
db->md = da.nd;
db->nd = da.md;
db->td = da.td;
if(da.td != 0)
{
for(p = 0;p < da.td; p++)
{
b->list[p].i = a.list[p].j;
b->list[p].j = a.list[p].i;
b->list[p].d = a.list[p].d;
}
}
}
/*
a为转置前的三元组顺序表,da是a的控制数据
三元组顺序表a按先行序后列序的顺序存放
b为转置后的三元组顺序表,db是b的控制数据
*/
void Transition2(SeqList a,TriType da,SeqList*b,TriType*db)
{
int p,q,v;
db->md = da.nd;
db->nd = da.md;
db->td = da.td;
if(da.td == 0) return 0;
else
{
q = 0;
for(v = 1;v <= da.nd; v++)
{
for(p = 0;p < da.td; p++)
{
if(a.list[0].j == v)
{
//寻找原矩阵中列下标值最小的
b->list[q].i = a.list[p].j;
b->list[q].j = a.list[p].i;
b->list[q].d = a.list[p].d;
q++;
}
}
}
}
}
例3:
将图A转置为图B
#include <stdio.h>
#define MaxSize 1000
typedef int elemtype;
typedef struct
{
int i; //行号
int j; //列号
elemtype d; //元素值
} DataType;
typedef struct
{
int md; //行数
int nd; //列数
int td; //非零元素个数
} TriType;
#include "SeqList.h"
void Transition(SeqList a,TriType da,SeqList*b,TriType*db)
{
int p,q,v;
db->md = da.nd;
db->nd = da.md;
db->td = da.td;
if(da.td != 0)
{
q = 0;
for(v = 1;v <= da.nd; v++)
{
for(p = 0;p < da.td; p++)
{
if(a.list[p].j == v)
{
b->list[q].i = a.list[p].j;
b->list[q].j = a.list[p].i;
b->list[q].d = a.list[p].d;
q++;
}
}
}
}
}
void main(void)
{
SeqList listA,listB;
TriType myA = {6,7,6},myB;
DataType a[] = {
{1,3,11},{1,5,17},{2,2,25},{4,1,19},{5,4,37},{6,7,50}
};
int i;
ListInitiate(&listA); //顺序表初始化
for(i = 0;i < myA.td; i++)
ListInsert(&listA,i,a[i]); //向顺序表第i个位置插入元素
printf("转置前-行数:%d\t列数:%d\t非零元数:%d\n",myA.md,myA.nd,myA.td);
printf("三元组元素依次为:\n");
for(i = 0;i < myA.td; i++)
printf("%d\t%d\t%d\n",listA.list[i].i,listA.list[i].j,listA.list[i].d);
printf("\n\n");
Transition(listA,myA,&listB,&myB); //转置
printf("转置后-行数:%d\t列数:%d\t非零元数:%d\n",myB.md,myB.nd,myB.td);
printf("三元组元素依次为:\n");
for(i = 0;i < myB.td; i++)
printf("%d\t%d\t%d\n",listB.list[i].i,listB.list[i].j,listB.list[i].d);
}