数组顺序存储表示和实现

实现:

/***************************************
数组的顺序表示和实现
by Rowandjj
2014/5/2
----------------
不管是多少维的数组,在内存中都是线性存储的,
数组中每个元素都对应着一个物理地址,它们之间满足一个线性的关系。

比如,3维数组,3*3*2架构,即A[3][3][2],对应常量为6,2,1
bounds    constants
  3           6
  3           2
  2           1
所以A[0][2][1]相对基地址的偏移为0*6+2*2+1 = 5

注:内存中实际排列情况如下:
A[0][0][0] A[0][0][1] A[0][1][0] A[0][1][1] A[0][2][0] A[0][2][1]...

***************************************/
#include<iostream>
#include<stdarg.h>
using namespace std;

#define MAX_ARRAY_DIM 8//数组维数最大值
//------------数组的顺序存储表示------------------------------
typedef int ElemType;
typedef struct _ARRAY_
{
    ElemType *pBase;//数组元素基址
    int dim;//维数
    int *pBounds;//维边界
    int *pContants;//数组映像函数常量
}Array,*pArray;

bool InitArray(pArray pArrayTemp,int iDim,...);    //初始化数组
bool DestroyArray(pArray pArrayTemp);//销毁数组
void TravelArray(pArray pArrayTemp);//遍历
bool Assign(pArray pArrayTemp,ElemType e,...);//若下标合法,将e的值赋给所指定的A的元素,并返回true
bool Locate(pArray pArrayTemp,va_list temp,int *offset);//求出指定元素在数组中的相对地址(偏移量)
bool Value(pArray pArrayTemp,ElemType *e,...);//获取指定位置上的数组值

bool InitArray(pArray pArrayTemp,int iDim,...)
{
    if(iDim<1 || iDim>MAX_ARRAY_DIM)
    {
        return false;
    }
    pArrayTemp->dim = iDim;
    int i = 0;

    pArrayTemp->pBounds = (int*)malloc(sizeof(int)*iDim);//为维边界申请内存
    if(pArrayTemp->pBounds == NULL)
    {
        return false;
    }

    va_list temp = {0};
    va_start(temp,iDim);
    int elemTotal = 1;
    for(i = 0; i < iDim; i++)
    {
        pArrayTemp->pBounds[i] = va_arg(temp,int);//给维边界赋值
        if(pArrayTemp->pBounds[i] < 0)
        {
            free(pArrayTemp->pBounds);
            return false;
        }
        elemTotal *= pArrayTemp->pBounds[i];//获取总的元素个数,即每一维的长度相乘
    }
    va_end(temp);
    pArrayTemp->pBase = (ElemType *)malloc(sizeof(ElemType)*elemTotal);//为每一个元素申请内存
    if(pArrayTemp->pBase == NULL)
    {
        free(pArrayTemp->pBounds);
        return false;
    }

    pArrayTemp->pContants = (int *)malloc(sizeof(int) * iDim);//为映射函数常量值申请内存
    if(pArrayTemp->pContants == NULL)
    {
        free(pArrayTemp->pBounds);
        free(pArrayTemp->pBase);
        return false;
    }
    pArrayTemp->pContants[iDim-1] = 1;
    for(i=iDim-2; i>=0; i--)
    {
        pArrayTemp->pContants[i] = pArrayTemp->pContants[i+1]*pArrayTemp->pBounds[i+1];//给映射函数常量赋值
    }
    return true;
}

bool DestroyArray(pArray pArrayTemp)
{
    if(pArrayTemp->pBase != NULL)
    {
        free(pArrayTemp->pBase);
        pArrayTemp->pBase = NULL;
    }
    if(pArrayTemp->pBounds != NULL)
    {
        free(pArrayTemp->pBounds);
        pArrayTemp->pBounds = NULL;
    }
    if(pArrayTemp->pContants != NULL)
    {
        free(pArrayTemp->pContants);
        pArrayTemp->pContants = NULL;
    }
    return true;
}

void TravelArray(pArray pArrayTemp)
{
    int i;
    cout<<"dim:"<<pArrayTemp->dim<<endl;
    cout<<"bounds:";
    for(i = 0; i < pArrayTemp->dim; i++)
    {
        cout<<pArrayTemp->pBounds[i]<<" ";
    }
    cout<<endl;
    cout<<"pConstants:";
    for(i = 0; i<pArrayTemp->dim; i++)
    {
        cout<<pArrayTemp->pContants[i]<<" ";
    }
    cout<<endl;
    cout<<"data:";
    int count = 1;
    for(i = 0; i < pArrayTemp->dim; i++)
    {
        count *= pArrayTemp->pBounds[i];
    }
    for(i = 0; i < count; i++)
    {
        cout<<pArrayTemp->pBase[i]<<" ";
    }
    cout<<endl;
}

bool Assign(pArray pArrayTemp,ElemType e,...)
{
    va_list temp = {0};
    int offset = 0;
    va_start(temp,e);
    bool result = Locate(pArrayTemp,temp,&offset);
    *(pArrayTemp->pBase + offset) = e;
    va_end(temp);
    return result;
}
bool Locate(pArray pArrayTemp,va_list temp,int *offset)
{
    int iTemp = 0;
    int i = 0;
    *offset = 0;//将偏移量初始化为0
    for(i = 0; i < pArrayTemp->dim; i++)
    {
        iTemp = va_arg(temp,int);
        *offset += iTemp*(pArrayTemp->pContants[i]);
    }
    return true;
}
bool Value(pArray pArrayTemp,ElemType *e,...)
{
    va_list temp;
    va_start(temp,e);
    bool result = false;
    int offset;
    result = Locate(pArrayTemp,temp,&offset);
    *e = pArrayTemp->pBase[offset];
    va_end(temp);
    return result;
}

测试:

int main()
{
    Array ArrayTemp = {0};
    InitArray(&ArrayTemp,3,3,2,2);
    int i = 0,j = 0,k = 0;
    for(i = 0; i<ArrayTemp.pBounds[0];i++)
    {
        for(j = 0; j < ArrayTemp.pBounds[1];j++)
        {
            for(k = 0; k <ArrayTemp.pBounds[2];k++)
            {
                Assign(&ArrayTemp,i*100+j*10+k,i,j,k);
            }
        }
    }
    ElemType e;
    Value(&ArrayTemp,&e,1,1,1);
    TravelArray(&ArrayTemp);
    cout<<"e = "<<e<<endl;
    DestroyArray(&ArrayTemp);
    return 0;
}

结果:

数组顺序存储表示和实现

时间: 2024-11-02 11:40:35

数组顺序存储表示和实现的相关文章

数组顺序存储二叉树

1.完全二叉树 完全二叉树由于其结构上的特点,通常采用顺序存储方式存储.一棵有n个结点的完全二叉树的所有结点从1到n编号,就得到结点的一个线性系列. 如下图:完全二叉树除最下面一层外,各层都被结点充满了,每一层结点的个数恰好是上一层结点个数的2倍,因此通过一个结点的编号就可以推知它的双亲结点及左,右孩子结点的编号: ① 当 2i ≤ n 时,结点 i 的左孩子是 2i,否则结点i没有左孩子: ② 当 2i+1 ≤ n 时,结点i的右孩子是 2i+1,否则结点i没有右孩子: ③ 当 i ≠ 1 时

杨辉三角(Pascal Triangle)的几种C语言实现及其复杂度分析

说明 本文给出杨辉三角的几种C语言实现,并简要分析典型方法的复杂度. 本文假定读者具备二项式定理.排列组合.求和等方面的数学知识. 一  基本概念 杨辉三角,又称贾宪三角.帕斯卡三角,是二项式系数在三角形中的一种几何排列.此处引用维基百科上的一张动态图以直观说明(原文链接http://zh.wikipedia.org/wiki/杨辉三角): 从上图可看出杨辉三角的几个显著特征: 1. 每行数值左右对称,且均为正整数. 2. 行数递增时,列数亦递增. 3. 除斜边上的1外,其余数值均等于其肩部两数

有向图的十字链表存储形式

十字链表是有向图的另一种链式存储结构.可以看成是将有向图的邻接表和逆邻接表(只考虑入度)结合起来得到的一种链表.在十字链表中,对应于有向图中每一个顶点有一个节点,每一条弧也有一个结点. 顶点之间是数组顺序存储,而弧是链式存储. 弧结点结构: 顶点结点结构: 十字链表形态: 实现: /*********************************************** 有向图的存储形式--十字链表 by Rowandjj 2014/6/27 ***********************

【TAC】第一周

TAC终于过去第一周了,至少在课程和习题意义上来说如此. 怎么说呢,颇费了一些时间和精力吧,有苦有甜,很遗憾没能全AC过去,最终还是败在了那道最小(大)生成树上,尽管它只是一个简单的并查集而已. 但说实话,并查集在三个月前看姥姥和黑皮书时,也没有十分走心吧.现在唯一能得出的结论就是,光听课看书抄笔记是完全没用的,必须亲手实现才能留下一点点的印象. 哎,看过的东西又尘归尘土归土了. 但也不是完全一点印象也没有的,比如还记得父节点表示法. 其他的,还多亏有了代码模板和提示,以及充分的讨论,才能顺利理

java集合框架之ArrayList

废话不多说直接进入正题,本文将一步步来分解ArrayList: 先看下ArrayList主要的成员变量: /** * Default initial capacity. 默认初始化容量10 */ private static final int DEFAULT_CAPACITY = 10; /** * Shared empty array instance used for empty instances. */ private static final Object[] EMPTY_ELEME

C++学习(二十九)(C语言部分)之 顺序表

一.数据结构组织 存放数据的方式 精心选择的数据结构可以提升效率 数据结构 1.逻辑结构 一对多关系 父与子 一对一关系 排队中 多对多关系 两地的路线 2.存储结构 数据存放的位置关系 顺序存储数据 一个挨着一个的存储(数组) 链式存储方式 二.线性表逻辑方面是线性关系 一对一线性 每一个元素有唯一的前驱和后继顺序存储的线性表 就是顺序表链式存储的线性表 就是链表 三.顺序表主要实现方式---->数组/动态数组顺序存储的线型表数据结构--->为了管理数据对数据进行操作--->增加 删除

C++ map set

C++ map set map 和 set 的内部数据结构是红黑树 PS:二叉树的存储方式 PSS: 散列表 vs 二叉查找(排序)树 红黑树 map 和 set 使用 map 和 set 的内部数据结构是红黑树 PS:二叉树的存储方式 二叉树既可以用链式存储,也可以用数组顺序存储.数组顺序存储的方式比较适合完全二叉树,其他类型的二叉树用数组存储会比较浪费存储空间.堆其实就是一种完全二叉树,最常用的存储方式就是数组. PSS: 散列表 vs 二叉查找(排序)树 散列表中的数据是无序存储的,如果要

数据结构——二叉树概述及其数组(顺序存储)表达法

树与二叉树: 什么是树呢?就是一个节点上会有很多分叉的数据结构.一般的,对于一棵树,我们需要的结构体为一个数据块和几个指针块,这就相当于很多个链表交织在了一起,实际上,链表也可以算是一种特殊的树,而我要讲的,也是一种特殊的树--二叉树. 对于树的各个节点,都有两个属性,称为度(degree),他的意思就是这个节点所拥有的子节点的数量.还有一个属性,称为深度(depth),指节点到根的距离. 什么是二叉树呢?顾名思义,就是度为二的树,它长这样: 如图所示,在链表中我们需要头(head),而在树中我

线性表之顺序存储结构(C语言动态数组实现)

线性表的定义:N个数据元素的有限序列 线性表从存储结构上分为:顺序存储结构(数组)和 链式存储结构(链表) 顺序存储结构:是用一段连续的内存空间存储表中的数据 L=(a1,a2,a3....an) 链式存储结构:是用一段一段连续的内存空间存储表中每一行的数据,段与段之间通过一个引用(指针)相互连接来,形成一个链式的存储结构 看到顺序存储结构的图示,我们可能会马上联想到C语言的数组.是的,数组就是一种典型的顺序存储数据结构.下面我通过一个实例,来实现对顺序存储结构中的数据增.删.改.查的操作. 首