数据结构及算法之数组

数组

  1 抽象数据类型数组的形式定义

ADT Array{
   数据对象: ji = 0,…,bi - 1, i = 1,2,…,n,
       D={ aj1j2…jn | n(>0)称为数组的维数,bi是数组第i维的长度。ji是数组元素的第i维的下标, aj1j2…jn ϵ ElemSet }
   数据关系: R = { R1,R2,…,R3}
       Ri = { <aj1…ji…jn , aj1…ji+1…jn> |
              0<=jk<=bk-1 , 1<=k<=n 且 k!=i,
              0<=ji<=bi-2 , aj1…ji…jn , aj1…ji+1…jn ϵ D,i=2,…,n}
   基本操作:
    InitArray( &A, n, bound1, …, boundn )
      操作结果:若数组n和各维长度合法,则构造相应的数组A,并返回OK。
    DestroyArray( &A )
      操作结果:销毁数组A。
    Value( A, &e, index1,…, indexn )
      初始条件:A是n维数组,e为元素变量,随后是n个下标值。
      操作结果:若各下标不超界,则e赋值为所指的A的元素值,并返回OK。
    Assgin( &A, e, index1,…, indexn )
      初始条件:A是n维数组,e为元素变量,随后是n个下标值。
      操作结果:若各下标不超界,则将e的值赋给所指的A的元素值,并返回OK。
}ADT Array

这是一个C语言风格的定义。当n=1时,n维数组就退化为定长的线性表。反之,n维数组也可以看成是线性表的推广。

  2 数组的顺序表示和实现

    由于数组一般不做插入和删除,也就是说,一旦建立了数组,则结构中的数据元素个数和元素之间的关系就不发生变动了。因此,采用顺序存储结构表示数组是自然的事了。由于存储单元是一维的结构,而数组是多维的结构,则用一组连续存储单元存放数组的数据元素就有个次序约定问题。
    下面仅用以行序为主序的存储结构为例子说明。
在这里插入图片描述
三维数组
在这里插入图片描述
在这里插入图片描述

   (1) 数组的顺序存储表示

#include <stdarg.h>          //标准头文件,提供宏va_start,va_arg和va_end,用于存取变长参数表
#define MAX_ARRAY_DIM  3    //假设数组维数的最大值为3
typedef struct{
	ElemType       *base;       //数组元素基址,由InitArray分配
	int             dim;        //数组维数
	int            *bounds;     //数组维界基址,由InitArray分配
	int            *constants;  //数组映像函数常量基址,由InitArray分配
}Array;

   (2) 基本操作

Status
InitArray( Array &A, int dim, ... ){
	//若维数dim和随后的各维长度合法,则构造相应的数组A,并返回OK。
	va_list var_arg;
	if( dim < 1 || dim > MAX_ARRAY_DIM )
		return ERROR;
	A.dim = dim;
	A.bounds = (int *)malloc( dim * sizeof( int ) );
	if( !A.bounds )
		exit(OVERFLOW);      //若各维长度合法,则存入A.bounds ,并求出A的元素总数elemtotal
	elemtotal = 1;
	va_start( var_arg, dim );   //var_arg是存放变长参数信息的数组
	for( i = 0; i < dim; i++ ){
		A.bounds[ i ] = va_arg( var_arg, int );
		if( A.bounds[ i ] < 0)
			return UNDERFLOW;
		elemtotal * = A.bounds[ i ];
	}
	va_end( var_arg );
	
	A.base = ( ElemType *)malloc( elemtotal * sizeof( ElemType ) );
	if( !A.base )
		exit( OVERFLOW );
	//求映像函数的常数ci,并存入A.constants[i-1],i=1,...,dim
	A.constants = (int *)malloc( dim * sizeof( int ) );
	if( !A.constants )
		exit( OVERFLOW );	
	A.constants[ dim - 1 ] = 1;     //L=1,指针的递减以元素的大小为单元
	for( i = dim - 2; i>=0; --i ){
		A.constants[ i ] = A.bounds[ i + 1 ] * A.constants[ i + 1 ];
	}
	return OK;
}
Status
DestroyArray( Array &A ){
	//销毁数组A
	if( !A.base )        return ERROR;
	free( A.base );      A.base = NULL;
	if( !A.bounds )        return ERROR;
	free( A.bounds );      A.bounds = NULL;	
	if( !A.constants )        return ERROR;
	free( A.constants );      A.constants = NULL;
	return OK;
}
Status
Locate( Array A, va_list ap, int &off ){
	//若ap指示的各下标值合法,则求出该元素在A中的相对地址off
	off = 0;
	for( i = 0; i<A.dim; ++i ){
		ind = va_arg( ap, int );
		if( ind < 0 || ind >= A.bounds[ i ] )
			return OVERFLOW;
		off + = A.constants[ i ] * ind;
	}
	return OK;
}
Status
Value( Array A, ElemType &e, ... ){
	//A是n维数组,e为元素变量,随后是n个下标值。
	//若各下标不超界,则e赋值为所指定的A的元素值,并返回OK。
	va_start( var_arg, e );
	if( ( result = Locate( A, var_arg, off )) <= 0 )
		return result;
	e = *( A.base + off );
	return OK;
}
Status
Assgin( Array &A, ElemType e, ... ){
	//A是n维数组,e为元素变量,随后是n个下标值
	//若下标不超界,则将e的值赋给所指定的A的元素,并返回OK。
	va_start( var_arg, e );
	if( ( result = Locate( A, var_arg, off )) <= 0 )
		return result;
	 *( A.base + off ) = e;
	return OK;	
}

  3 矩阵的压缩存储

  所谓压缩存储是指:为多个值相同的元只分配一个存储空间;对零元不分配空间。
  假若值相同的元素或者零元素在矩阵中的分布有一定的规律,则我们称此类矩阵为特殊矩阵;反之,称为稀疏矩阵。
  特殊矩阵在这不做讲解,以下仅为稀疏矩阵。

   (1) 抽象数据类型稀疏矩阵的形式定义

ADT SparseMatrix{
   数据对象:D = { aij | i = 1,2,…m; j = 1, 2, …, n; ai,j ϵ ElemSet ,m 和 n 分别称为矩阵的行数和列数 }
   数据关系:R = { Row, Col }
         Row = { <ai,j, ai,j+1> | 1<=i<=m,1<=j<=n-1}
         Col = {<ai,j, ai+1,j> | 1<=i<=m-1,1<=j<=n }
   基本操作:
      CreateSMatrix( &M )
       操作结果:创建稀疏矩阵M。
     DestroySMatrix( &M )
       初始条件:稀疏矩阵M存在。
       操作结果:销毁稀疏矩阵M。
     PrintSMatrix( M )
       初始条件:稀疏矩阵M存在。
       操作结果:输出稀疏矩阵M。
     CopySMatrix( M, &T )
       初始条件:稀疏矩阵M存在。
       操作结果:由稀疏矩阵M复制得到T。
     AddSMatrix( M , N, &Q )
       初始条件:稀疏矩阵M与N的行数和列数对应相等。
       操作结果:求稀疏矩阵和Q=M+N。
     SubSMatrix( M , N, &Q )
       初始条件:稀疏矩阵M与N的行数和列数对应相等。
       操作结果:求稀疏矩阵差Q=M-N。
     MultSMatrix( M , N, &Q )
       初始条件:稀疏矩阵M的列数等于N的行数。
       操作结果:求稀疏矩阵乘积Q=MxN。
     TransposeSMatrix( M, &T )
       初始条件:稀疏矩阵M存在。
       操作结果:求稀疏矩阵M的转置矩阵T。
}ADT SparseMatrix

   (2) 稀疏矩阵的三元组顺序存储表示

  按照压缩存储的概念,只存储稀疏矩阵的非零元。因此,除了存储非零元的值外,还必须同时记下它的所在行和列的位置(i,j)。反之,一个三元组(i,j,aij)唯一确定了矩阵A是一个非零元。

#define MAXSIZE 12500      //假设非零元素个数的最大值为12500
typedef struct{
	int         i,j;       //非零元的行下标和列下标
	ElemType     e;
}Triple;

typedef struct{
	Triple     data[ MAXSIZE +1 ];      //非零元三元组表,data[0]未用
	int         mu,nu,tu;              //矩阵的函数,列数和非零元素个数
}TSMatrix;

   (3) 稀疏矩阵的十字链表存储表示

typedef struct QLNode{
	int              i,j;            //该非零元的行和列的下标
	ElemType          e;
	struct QLNode   *right,*down   //该非零元所所在行表和列表的后继链域
}QLNode,*QLink;

typedef struct{
	QLink    *rhead,*chead;         //行和列链表头指针向量基址
	int       mu,nu.tu;             //稀疏矩阵的行数,列数和非零元个数
}CrossList;
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
合并排序是一种经典的排序算法,它基于分治策略将一个大问题分解为多个小问题,并通过递归的方式解决这些小问题,最后将结果合并得到有序序列。下面是合并排序的数据结构算法设计: 1. 数据结构: - 数组:合并排序通常使用数组作为数据结构,因为数组可以通过索引快速访问元素。 2. 算法设计: - 分解:将待排序的数组分解为两个子数组,直到每个子数组只有一个元素。 - 合并:将两个有序的子数组合并为一个有序的数组。 - 递归:对每个子数组递归地进行分解和合并操作,直到最终得到完全有序的数组。 具体的合并排序算法步骤如下: 1. 如果数组长度小于等于1,则无需排序,直接返回。 2. 将数组平均分成两个子数组,分别对这两个子数组进行递归调用合并排序。 3. 合并两个有序的子数组,得到一个有序的数组。 4. 返回合并后的有序数组。 合并两个有序子数组的过程如下: . 创建一个临时数组,用于存放合并后的结果。 2. 初始化两个指针,分别指向两个子数组的起始位置。 3. 比较两个指针所指向的元素,将较小的元素放入临时数组,并将对应指针后移一位。 4. 重复步骤3,直到其中一个子数组的元素全部放入临时数组。 5. 将剩余子数组的元素依次放入临时数组。 6. 将临时数组中的元素复制回原数组的对应位置。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值