精华内容
下载资源
问答
  • 有什么用看例子: // // 定义数组:Dim 数组名(下标),数组长度已被锁定! Dim GG(3) //定义一个数组GG,下标为3,数组元素数为4(公式:数组下标+1=数组中元素个数) GG(0)=8 GG(1)=3 GG(2)=4 GG(3)=6 // 上面是数组...

    前言

    如果你没有编程基础,对数组还没什么了解,建议不要学习本帖知识,先学习了解数组的基本知识。对数组有基本了解往下看,
    直入主题,什么是动态数组?怎么用?概念上的东西不多说了,看例子!

    正文

    // 什么是动态数组?什么时候用?有什么用看例子:
    //
    // 定义数组:Dim 数组名(下标),数组长度已被锁定!

    Dim GG(3) //定义一个数组GG,下标为3,数组元素数为4(公式:数组下标+1=数组中元素个数)
    GG(0)=8
    GG(1)=3
    GG(2)=4
    GG(3)=6
    

    // 上面是数组的定义与赋值,GG(4)是不存在的,下标最大值是3,不可能有GG(4),如果代码使用GG(4)那就叫下标越界!
    //【假设】如果我想给这个数组下标扩大!GG(4)=1,GG(5)=0,如何加进去?
    //【错解】直接添加GG(4)=1,GG(5)=0
    //【正解】不可以直接添加!因原数组长度已被锁定。动态数组就用在此时!

    Dim 新数组() '定义新数组,长度未锁定所以括号里不写下标值,本行可省略
    For 计数 = 0 To UBound(GG)
    ReDim Preserve 新数组(计数)
    TracePrint UBound(新数组) '返回新数组长度
    新数组(计数)=GG(计数)
    Next
    ReDim Preserve 新数组(5) //循环结束,新数组长度为3,而我们要将其变成5,该行不可省!
    新数组(4) = 1
    新数组(5) = 0 //是不是搞定了呢?测试一下是否成功了?!激动ing
    

    //0ReDim Preserve 新数组(100) //删除本行首的“//0”再执行会发现数组长度再次被改变,不会报错
    MessageBox Join(新数组, “|”) '弹出结果,方便我们分析
    //
    // 综上所述,已被定义的数组,已确定其下标则长度会被锁定,不可以再改变其长度,不能添加新元素。如需要扩大下标添加新元素的情况须使用动态数组!
    // 动态数组的声明方式为: ReDim 数组名(新下标),如果需要保留原数组元素,那么需要添加Preserve,写法即:ReDim Preserve 数组名(新下标)

    引申
    上文只对一维数组动态数组的使用做了介绍,多维的情况不多做讨论,感觉用的不多,印象里多维的规则是只可以改变最后一维的下标!!有兴趣的自己找资料看看

    实例

    课题:现用户要求按一次键存入一次按键码,每次记录按键码最后以换行排列?
    说明:动态数组用在类似的课题中,非常方便!用户按键次数是未知的(即数组长度未知)
    实现:

    下标=0 '给数组下标赋初值
    Do
    相识 = WaitKey() '存入按键码
    ReDim Preserve 数组(下标) '动态数组,改变数组长度或说改变下标
    数组(下标) = 相识
    下标=下标+1 '下标自增
    Loop
    Sub OnScriptExit()
    MessageBox Join(数组, vbcrlf)
    End Sub
    
    展开全文
  • 那么问题来了,这两类数据结构有什么区别呢?为什么Python的列表,支持存放不同类型的数据,而R语言的向量只能放同一个类型的数据呢?还有,为什么R语言的向量化运算函数(如sum, nchar)速度会显著性高于R的循环呢?...

    如果你用过R语言,那么一定用过向量,如果用Python,那么一定用过列表。那么问题来了,这两类数据结构有什么区别呢?

    为什么Python的列表,支持存放不同类型的数据,而R语言的向量只能放同一个类型的数据呢?还有,为什么R语言的向量化运算函数(如sum, nchar)速度会显著性高于R的循环呢?

    对于下面的R代码,那种循环更好呢?# loop 1a 

    }# loop 2a 

    a[i] = i

    }

    要想解答这些问题,就必须得学习一下数组。数组是一种线性表数据结构,他在一段连续内存空间中存储相同大小的元素。这里有两个关键点,第一是线性表,也就是说数组里面的元素只有前后关系,同样属于线性表数据结构的还有链表、队列和栈,与之相反的是非线性表数据结构,例如树和图。

    线性表和非线性表

    第二是连续内存,且里面的元素大小相同,这样子当知道数组的第一个元素的内存位置时,就可以迅速计算出第n个元素的内存地址,并获取该地址的存储内容。

    随机访问

    有利就有弊。由于数组要占用一组连续的内存空间,当你要存储的数据要占据非常大的空间时,就会面临内存中找不到位置的尴尬情形。此外,为了保证数据存储的连续性,那么在你插入和删除数据的时候都要进行额外的数据移动操作,这些操作的时间复杂度是

    。如果数据已经满了,那么加入新的数据时就需要在内存中申请新的空间,同时将现有数据迁移过去。

    插入操作

    尽管如此,数组依旧是最常用的数据结构,毕竟数组和CPU和缓存机制非常契合,在数据处理上效率较高。

    在C语言中,数组的声明方式有如下方法:float averages[200]; //在内存中预留200个位置char word[] = { 'H', 'e', 'l', 'l', 'o', '!'}; // 让C自动确定数组的大小char *words[] = {"hello", "world"}; 字符串数组

    此外,指针与数组的关系十分密切,一般能用数组下标实现的操作,都能用数组完成。过去的时候,指针操作的速度会快于数组下标操作,但是随着编译器的优化,基本上两者的性能持平了。考虑指针实现的程序理解比较困难,因此更推荐用数组。示例:int a[10]; //声明一个长度为10的存放整型的数组int *pa;  //声明一个指向整型的指针pa = &a[0]; // 将数组a的起始地址赋值给指针//等价于 pa = a;

    那么a[i]  等价于 *(pa + i ) ,  无论数组a中元素的类型或数组长度是什么,该结论始终成立。 ”指针加1“就意味着pa + 1 指向pa所指向对象的下一个对象。简而言之,一个通过数组和下标实现的表达式可等价地通过指针和偏移量实现。

    但是,指针和数组还是有区别的,指针是一个变量,数组名不是变量。在函数定义中,形式参数char s[]; 和char *s 是等价的,这是因为把数组名传递给函数时,实际传递的时该数组的第一个元素的地址。

    R语言的向量和Python的列表还不是普通的数组,因为他们的大小可变,同样特点的还有C++的标准库类型vector, 还有Java的ArrayList和Vector类,都支持动态进行扩容。举个C++的例子#include #include using std::cin;using std::vector;string word;vector  text;while (cin >> word){

    text

    }

    当然C语言本身并没有这个功能,所以我就尝试着自己写了一个非常简单的实现,依旧分为两个头文件和C文件。

    darray.h如下:#ifndef _DARRAY_H                                           #define _DARRAY_H

    typedef unsigned int position;

    /* define the data struct */                                typedef struct _cell cell;                                  typedef struct _darray darray;

    /* define the manipulate function of darray */

    darray *dCreate(char *strings[], int ssize);

    darray *dInsert(darray *d, position pos, char *string);

    darray *dExpand(darray *d, int ssize);

    void dDestroy(darray *d);

    void dRemove(darray *d, position pos);

    void dPrint(darray *d);

    #endif

    darray.c:#include #include #include "dbg.h"#include "darray.h"// 用deleted标注删除,不做实际的搬移操作enum status {empty, deleted, legitimate };typedef struct _cell {

    enum status info;    char *string ;

    } cell;typedef struct _darray{

    int size;    int load;

    cell *cells;

    } darray;// 根据初始大小申请内存darray *dCreate(char *strings[], int ssize){

    darray *d;

    d = malloc(sizeof(darray));

    d->size = 2 * ssize;

    d->load = 0;

    d->cells = calloc(d->size, sizeof(cell));

    // initialize the array

    int i;    for (i = 0; i 

    d->cells[i].info = legitimate;

    d->cells[i].string = strings[i];

    d->load ++;

    }

    debug("i shoule be %d", i);    for (; i size; i++){

    d->cells[i].info = empty;

    }    return d;

    }//进行扩容darray *dExpand(darray *d, int ssize){

    darray *newArray;

    newArray = malloc(sizeof(darray));

    newArray->size = 2 * ssize;

    newArray->cells = calloc(newArray->size, sizeof(cell));

    newArray->load = 0;    int i;    int j = 0;        //复制元素

    for (i = 0; i size; i++){        if( d->cells[i].info == legitimate){

    newArray->cells[j].string = d->cells[i].string;

    debug("new arrys cell %d is %s", j, newArray->cells[j].string);

    newArray->cells[j].info = legitimate;

    newArray->load++ ;

    j++ ;

    }

    }    for (; j size; j++){

    newArray->cells[j].info = empty;

    }        //释放原来的内存

    dDestroy(d);    return newArray;

    }//插入操作darray *dInsert(darray *d, position pos, char *string){    if (d->load + 1 > d->size ){

    d = dExpand(d, d->size);

    }    if (pos > d->size ){

    d = dExpand(d, pos);

    }

    debug("size of darray is %d", d->size);    if ( d->cells[pos].info == deleted ||

    d->cells[pos].info == empty){

    d->cells[pos].info = legitimate;

    d->cells[pos].string = string;

    } else{        int i = d->size;

    d->cells[i].info = legitimate;        for (; i > pos; i--){

    d->cells[i].string = d->cells[i-1].string;

    }

    d->cells[pos].string = string;

    }    return d;

    }//删除操作void dRemove(darray *d, position pos){

    d->cells[pos].info = deleted;

    }//输出元素void dPrint(darray *d){    int i = 0;    for (i = 0; i size; i++){        if ( d->cells[i].info == legitimate)            printf("%d \t %s \n", i, d->cells[i].string);

    }    putchar('\n');

    }void dDestroy(darray *d){    free(d->cells);    free(d);

    }int main(int argc, char *argv[]){

    darray *test;    char *input[] = {"hello", "my", "world","!"} ;

    test = dCreate(input, 4);

    dPrint(test);    char *h = "hello";

    test = dInsert(test, 10, h);

    dPrint(test);

    dRemove(test,1);

    dPrint(test);

    dDestroy(test);    return 0;

    }目前代码还存在一些问题,因为我只是将元素标记了删除,那么后续删除同一个位置时需要向后移动才行。同样插入操作也会存在bug。但是能这样子写代码对之前只能hello world的我已经是很大进步了。

    解答开篇: Python的列表中存放的是元素的引用,并非元素本身,因此可以放任意类型的数据,其实和R语言的list更加对应。而R语言的向量则更加接近数组结构。

    当你使用a

    作者:hoptop

    链接:https://www.jianshu.com/p/ec5f727e5650

    展开全文
  • 数组和动态数组

    2019-12-03 11:10:31
    还是记录一下,数组、数组指针和动态数组什么的,我比较爱混的问题,和一些记不住的东西。 1、数组的基本应用 C++ 支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。 1.1、数组的定义 //type...

    0、前言

    本来想把数组的各种复习记录一下。但是我实在太懒,不想重复到处都有的东西。用的时候再百度吧。
    还是记录一下,数组、数组指针和动态数组什么的,我比较爱混的问题,和一些记不住的东西。

    1、数组

    C++ 支持数组数据结构,它可以存储一个固定大小相同类型元素的顺序集合。

    1.1、数组的定义

    //type arrayName [ arraySize ];
    double balance[10];
    float temperature [100] ; // 100 个 float 值的数组
    char letter [2 6] ;    // 26 个 char 值的数组
    double size [1200] ; // 1200 个 double 值的数组
    string name [10] ; // 10 个 string 对象的数组
    

    这叫做一维数组。arraySize 必须是一个大于零的整数常量,例如,要声明一个类型为 double 的包含 10 个元素的数组 balance。
    由于数组是在编译的时候定义的,不是在运行的时候决定大小的。所以arraySize 必须是常量或常量表达式。

    1.2、初始化

    double balance1[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
    double balance2[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
    balance1[4] = 50.0;
    

    大括号 { } 之间的值的数目不能大于我们在数组声明时在方括号 [ ] 中指定的元素数目。
    如果您省略掉了数组的大小,数组的大小则为初始化时元素的个数。因此,balance1和balance2相同。

    1.3、访问

    double salary = balance[9];
    

    1.4、删除数组

    数组分配在栈,生命周期结束,就会清理。不像动态分配的数组需要手动删除。

    2、数组和函数

    2.1、函数的参数是数组

    传递参数是数组有如下3中形式:

    void myFunction(int *param)
    {
    .
    }
    
    void myFunction(int param[10])
    {
    .
    }
    
    void myFunction(int param[])
    {
    .
    }
    

    这三种形式传递的都是一个指针,只是表现形式不同,而且对于数组的大小不确定,需要编程时自己自己控制。

    2.2、函数的返回值是数组

    函数返回数组,只有数组中函数中定义的时候才需要返回。但是局部变量定义的数组,在函数返回后就结束生命周期释放内存了。所以只有动态分配内存的数组可以返回。我们将在下面数组的动态分配中说。

    最近复习看到返回static的局部变量数组这个方法。
    从原理上来说,static的变量是在第一次运行时候声明的,到类的生命周期结束才结束。虽然是在函数内生命的,离开这个函数的范围后,变量是不见,但是数组 r的内存空间并没有释放。所以返回数组地址可以获得内容。(这样总总是感觉很别扭。欢迎讨论。)
    测试代码如下:

    int * getData( )
    {
        static int  r[10];
        for (int i = 0; i < 10; ++i)
        {
            r[i] = i;
        }
        
        return r;
    }
    
    int main(int argc, const char * argv[]) {
    
        int * dd = getData();
        
        for (int i=0;i<10 ; i++) {
            std::cout<<dd[i]<<" ";
        }
    }
    

    3、数组的动态内存分配

    3.1、数组动态内存分配的原因:

    1、在静态数组定义时数量必须时常量,就是必须在编译时确定数组的长度,太不灵活。
    2、静态数组分配在栈上,程序的栈内存很有限。

    相对的动态数组:
    1、可以在运行时候,在确定数组长度。
    2、内存分配在堆上。可以自行管理数组的生命周期。

    3.2、动态数组

    关于动态数组的应用,下面代码十分清晰详细了。
    代码来源:https://www.cnblogs.com/chengjundu/p/11039148.html

    #ifndef DyArray_H
    #define DyArray_H
    
    #include <iostream>
    
    //一维数组
    void oneDimensionalArray()
    {
        //定义一个长度为10的数组
        int* array = new int[10];
        //赋值
        for(int i = 0; i < 10; i++)
        {
            array[i] = i*2;
        }
        //打印
        for(int i = 0; i < 10; i++)
        {
            std::cout << i << " : " << array[i] << std::endl;
        }
        //释放内存
        delete[] array;
    }
    
    //二维数组
    void twoDimensionalArray()
    {
        //定义一个2*10的二维数组
        int** array = new int*[2];
        for(int i = 0; i < 2; i++)
        {
            array[i] = new int[10];
        }
        //赋值
        for(int i = 0; i < 2; i++)
        {
            for(int j = 0; j < 10; j++)
            {
                array[i][j] = i*10 + j;
            }
        }
        //打印
        for(int i = 0; i < 2; i++)
        {
            for(int j = 0; j < 10; j++)
            {
                std::cout << "(" << i << ", " << j << ")" << array[i][j] << std::endl;
            }
        }
        //释放内存
        for(int i = 0; i < 2; i++)
        {
            delete[] array[i];
        }
        
        delete[] array;
    }
    
    //三维数组
    void threeDimensionalArray()
    {
        //定义一个3*10*20的数组
        int*** array = new int** [3];
        
        for(int i = 0; i < 3; i++)
        {
            array[i] = new int*[10];
            for(int j = 0; j < 10; j++)
            {
                array[i][j] = new int[20];
            }
        }
        //赋值
        for (int i = 0; i < 3; i++)
        {
            for(int j = 0; j < 10; j++)
            {
                for(int k = 0; k < 20; k++)
                {
                    array[i][j][k] = i*100 + j*10 + k;
                }
            }
        }
        //打印
        for (int i = 0; i < 3; i++)
        {
            for(int j = 0; j < 10; j++)
            {
                for(int k = 0; k < 20; k++)
                {
                    char str[64];
                    sprintf(str, "(%d, %d, %d): ", i, j, k);
                    std::cout << str << array[i][j][k] <<std::endl;
                }
            }
        }
        //释放内存
        for (int i = 0; i < 3; i++)
        {
            for(int j = 0; j < 10; j++)
            {
                delete[] array[i][j];
            }
        }
        for (int i = 0; i < 3; i++)
        {
            delete[] array[i];
        }
        
        delete[] array;
        
    }
    
    
    #endif /* DyArray_H */
    
    

    4、其它

    4.1、sizeof

    对静态数组名进行sizeof运算时,结果是整个数组占用空间的大小;
    因此可以用sizeof(数组名)/sizeof(*数组名)来获取数组的长度。

     int a[5]; 
     int s1 = sizeof(a);	// 4*5=20
     int s2 = sizeof(*a);	// 4
    

    因为整个数组共占20字节,首个元素(int型)占4字节。

    int * a = new int[7];
    int s1 = sizeof(a);	// 4
    int s2 = sizeof(b);	// 4
    

    因为地址位数为4字节,int型也占4字节。

    静态数组作为函数参数时,在函数内对数组名进行sizeof运算,结果为4,因为此时数组名代表的指针即一个地址,占用4个字节的内存(因为在传递数组名的参数时,编译器对数组的长度不做检查)。对动态数组的函数名,无论何时进行sizeof运算,得到的结果都是4.

    4.2、数组越界

    静态数组和动态数组最经常饭的错误,就是数组越界。现象是崩溃。

    new出来的数组都调用默认构造函数对数组对象进行初始化了。如果是int这里原始的数据类型,需要在new后面添加(),才会进行初始化。代码如下:

    int * aa = new int[10]();
    

    ps: 参考文章列表:

    https://www.runoob.com/cplusplus/cpp-arrays.html
    https://www.runoob.com/cplusplus/cpp-multi-dimensional-arrays.html
    https://www.runoob.com/cplusplus/cpp-pointer-to-an-array.html
    https://www.runoob.com/cplusplus/cpp-passing-arrays-to-functions.html
    https://www.runoob.com/cplusplus/cpp-return-arrays-from-function.html

    http://c.biancheng.net/view/1414.html
    详细,完整,图示清晰。讲了数组在内存中的分配方式。适合初学者。
    最后,还深入讲解了数组越界的形成。

    动态数组相关参考文章:
    https://www.jianshu.com/p/ef413611c4af
    https://blog.csdn.net/summer00072/article/details/80609427

    https://www.cnblogs.com/chengjundu/p/11039148.html
    数组动态分配内存。
    定义,分配内存,初始化,访问和删除。代码清晰。用于快速查询

    https://www.cnblogs.com/lidabo/p/9664396.html
    数组的动态内存分配的 细节问题,说的很好。

    https://blog.csdn.net/manchengpiaoxue/article/details/83145476
    有些不一样的东西。

    展开全文
  • 那么问题来了,这两类数据结构有什么区别呢? 为什么Python的列表,支持存放不同类型的数据,而R语言的向量只能放同一个类型的数据呢?还有,为什么R语言的向量化运算函数(如sum, nchar)速度会显著性高于R的循环呢?...
        

    如果你用过R语言,那么一定用过向量,如果用Python,那么一定用过列表。那么问题来了,这两类数据结构有什么区别呢?

    为什么Python的列表,支持存放不同类型的数据,而R语言的向量只能放同一个类型的数据呢?还有,为什么R语言的向量化运算函数(如sum, nchar)速度会显著性高于R的循环呢?

    对于下面的R代码,那种循环更好呢?

    # loop 1
    a <- c()
    for (i in 1:1000){
       a <- c(a,i)
    }
    # loop 2
    a <- vector(length=1000)
    for (i in 1:1000){
        a[i] = i
    }
    

    要想解答这些问题,就必须得学习一下数组。数组是一种线性表数据结构,他在一段连续内存空间中存储相同大小的元素。这里有两个关键点,第一是线性表,也就是说数组里面的元素只有前后关系,同样属于线性表数据结构的还有链表、队列和栈,与之相反的是非线性表数据结构,例如树和图。

    2013053-152c4df98996d682.png
    线性表和非线性表

    第二是连续内存,且里面的元素大小相同,这样子当知道数组的第一个元素的内存位置时,就可以迅速计算出第n个元素的内存地址,并获取该地址的存储内容。

    2013053-27a90a7d5c06090e.png
    随机访问

    有利就有弊。由于数组要占用一组连续的内存空间,当你要存储的数据要占据非常大的空间时,就会面临内存中找不到位置的尴尬情形。此外,为了保证数据存储的连续性,那么在你插入和删除数据的时候都要进行额外的数据移动操作,这些操作的时间复杂度是0(n)。如果数据已经满了,那么加入新的数据时就需要在内存中申请新的空间,同时将现有数据迁移过去。

    2013053-206c3877b49fb19d.png
    插入操作

    尽管如此,数组依旧是最常用的数据结构,毕竟数组和CPU和缓存机制非常契合,在数据处理上效率较高。

    在C语言中,数组的声明方式有如下方法:

    float averages[200]; //在内存中预留200个位置
    char word[] = { 'H', 'e', 'l', 'l', 'o', '!'}; // 让C自动确定数组的大小
    char *words[] = {"hello", "world"}; 字符串数组
    

    此外,指针与数组的关系十分密切,一般能用数组下标实现的操作,都能用数组完成。过去的时候,指针操作的速度会快于数组下标操作,但是随着编译器的优化,基本上两者的性能持平了。考虑指针实现的程序理解比较困难,因此更推荐用数组。示例:

    int a[10]; //声明一个长度为10的存放整型的数组
    int *pa;  //声明一个指向整型的指针
    pa = &a[0]; // 将数组a的起始地址赋值给指针
    //等价于 pa = a;
    

    那么a[i] 等价于 *(pa + i ) , 无论数组a中元素的类型或数组长度是什么,该结论始终成立。 ”指针加1“就意味着pa + 1 指向pa所指向对象的下一个对象。简而言之,一个通过数组和下标实现的表达式可等价地通过指针和偏移量实现

    但是,指针和数组还是有区别的,指针是一个变量,数组名不是变量。在函数定义中,形式参数char s[];char *s 是等价的,这是因为把数组名传递给函数时,实际传递的时该数组的第一个元素的地址。

    R语言的向量和Python的列表还不是普通的数组,因为他们的大小可变,同样特点的还有C++的标准库类型vector, 还有Java的ArrayList和Vector类,都支持动态进行扩容。举个C++的例子

    #include <vector>
    #include <iostream>
    
    using std::cin;
    using std::vector;
    
    string word;
    vector<string>  text;
    while (cin >> word){
      text
    }
    

    当然C语言本身并没有这个功能,所以我就尝试着自己写了一个非常简单的实现,依旧分为两个头文件和C文件。

    darray.h如下:

    #ifndef _DARRAY_H                                           
    #define _DARRAY_H                                           
                                                                
    typedef unsigned int position;                              
                                                                
    /* define the data struct */                                
    typedef struct _cell cell;                                  
    typedef struct _darray darray;                              
                                                                
    /* define the manipulate function of darray */              
                                                                
    darray *dCreate(char *strings[], int ssize);                
    darray *dInsert(darray *d, position pos, char *string);     
    darray *dExpand(darray *d, int ssize);                      
    void dDestroy(darray *d);                                   
    void dRemove(darray *d, position pos);                      
    void dPrint(darray *d);                                     
                                                                
    #endif                                                      
    

    darray.c:

    #include <stdio.h>
    #include <stdlib.h>
    #include "dbg.h"
    #include "darray.h"
    
    // 用deleted标注删除,不做实际的搬移操作
    enum status {empty, deleted, legitimate };
    
    typedef struct _cell {
        enum status info;
        char *string ;
    } cell;
    
    typedef struct _darray{
        int size;
        int load;
        cell *cells;
    } darray;
    
    // 根据初始大小申请内存
    darray *dCreate(char *strings[], int ssize)
    {
        darray *d;
        d = malloc(sizeof(darray));
        d->size = 2 * ssize;
        d->load = 0;
        d->cells = calloc(d->size, sizeof(cell));
        
        // initialize the array
        int i;
        for (i = 0; i < ssize; i++){
            d->cells[i].info = legitimate;
            d->cells[i].string = strings[i];    
            d->load ++;
        }
        debug("i shoule be %d", i);
        for (; i < d->size; i++){
            d->cells[i].info = empty;   
        }
        return d;
    }
    //进行扩容
    darray *dExpand(darray *d, int ssize)
    {
        darray *newArray;
        newArray = malloc(sizeof(darray));
        newArray->size = 2 * ssize;
        newArray->cells = calloc(newArray->size, sizeof(cell));
        newArray->load = 0;
        int i;
        int j = 0;
            //复制元素
        for (i = 0; i < d->size; i++){
            if( d->cells[i].info == legitimate){
                newArray->cells[j].string = d->cells[i].string; 
                debug("new arrys cell %d is %s", j, newArray->cells[j].string);
                newArray->cells[j].info = legitimate;
                newArray->load++ ;
                j++ ;
            }
        }
        for (; j < newArray->size; j++){
            newArray->cells[j].info = empty;
        }
            //释放原来的内存
        dDestroy(d);
        return newArray;
    }
    
    //插入操作
    darray *dInsert(darray *d, position pos, char *string)
    {
        if (d->load + 1 > d->size ){
            d = dExpand(d, d->size);
        }
    
        if (pos > d->size ){
            d = dExpand(d, pos);
        }
        debug("size of darray is %d", d->size);
        if ( d->cells[pos].info == deleted ||
                d->cells[pos].info == empty){
            d->cells[pos].info = legitimate;
            d->cells[pos].string = string;
        } else{
            int i = d->size;
            d->cells[i].info = legitimate;
            for (; i > pos; i--){
                d->cells[i].string = d->cells[i-1].string;
            }
            d->cells[pos].string = string;
        }
        return d;
    
    }
    //删除操作
    void dRemove(darray *d, position pos){
        d->cells[pos].info = deleted;
    }
    //输出元素
    void dPrint(darray *d)
    {
        int i = 0;
        for (i = 0; i < d->size; i++){
            if ( d->cells[i].info == legitimate)
                printf("%d \t %s \n", i, d->cells[i].string);
        }
        putchar('\n');
    }
    
    void dDestroy(darray *d)
    {
        free(d->cells);
        free(d);
    }
    
    int main(int argc, char *argv[])
    {
        darray *test;
        char *input[] = {"hello", "my", "world","!"} ;
        test = dCreate(input, 4);
        dPrint(test);
        char *h = "hello";
        test = dInsert(test, 10, h);
        dPrint(test);
        dRemove(test,1);
        dPrint(test);
        dDestroy(test);
        return 0;
    
    }
    
    

    目前代码还存在一些问题,因为我只是将元素标记了删除,那么后续删除同一个位置时需要向后移动才行。同样插入操作也会存在bug。但是能这样子写代码对之前只能hello world的我已经是很大进步了。

    解答开篇: Python的列表中存放的是元素的引用,并非元素本身,因此可以放任意类型的数据,其实和R语言的list更加对应。而R语言的向量则更加接近数组结构。

    当你使用a <c()的结果是在内存中申请了一块固定大小的空间。之后每次的a<- c(a, i)的效果就是在内存不断申请新空间,加入元素,因此时间消耗会很明显。所以,事先声明足够大的空间然后进行赋值操作才会比较经济。

    当我看C++ Primer(第五版)的vector一节时(P91页),里面提到,C++里面反而不应该像C,Java那样事先声明元素数目。事先声明元素大小反而会降低效率。

    展开全文
  • 现在直奔主题, 因为数组是连续存储的所以了随机访问的特性,因此数组可以索引来访问,时间复杂度是O(1)。既然可以索引访问那么现在请看,假如我现在要访问a[k]:下标从0开始:a[k]_add= base_add+ k * type_...
  • 动态数组1

    2019-09-07 23:24:39
    动态数组实现线性表 什么是线性表: 线性表,由零个或多个数据元素组成的有限序列。就像排队一样,只有第一个由唯一的后继,最后一个唯一的前驱,其他的都唯一的前驱和后继。 线性表的顺序存储结构 指的是...
  • 关于数组和指针的应用,第一个想到的就是指针和动态内存分配函数联,来构建动态数组了。 动态内存分配函数分为4个函数: (1)函数malloc() 用于分配若干字节的内存空间,返回一个指向该内存首地址的指针。 void *...
  • vba 数组(动态数组

    千次阅读 2013-10-15 10:38:08
    主要内容: 本文章主要介绍VBA中,数组的使用,特别介绍动态数组的使用,并简单事例,帮助理解。 数组是我们经常用到的存储数据的一种媒介,他到底是什么呢? 一、定长数组 数组是具有相同数据类型并且共享...
  • 基于Java实现动态数组

    2020-07-20 00:01:51
    实现动态扩容的方式很多,但是在数组的后面接上一段内存是明显不行的,我们需要做的就是重新申请一个更大容量的数组,这样才是可行的方法,但是问题又来了用什么方式来申请才能够最有效的扩容,
  • 动态数组的创建

    2017-04-07 08:16:39
    首先,我们为什么用动态数组,我认为主要是数据过大而且主要是出现二维数组的时候,如果是一维数据,没啥好说,开大点就解决了,但是用到二维时就不好办了 比如天梯赛的那道 功夫传人,固定的数组就没法解决 ...
  • 如果是想生成一个二维数组,最后静态声明,或则二次声明redim 一个足够大的动态数组 1.2 出错的原因是什么? redim时只有最后1维可变化,redim不太适合和循环搭配,即使 redim preserve也不行! 你装数据时...
  • 什么动态数组? 在编程中,我们经常用到数组这种最基本的数据结构。而我们一般的都是定长数组,动态数组用的会比较少。但是有时,定长数组并不能很好地满足我们的要求,于是我们就要使用用动态数组。 在JAVA中...
  • 如何使用动态数组

    千次阅读 2013-08-28 17:14:33
    Q: 我定义了一个数组  int i =6789 ;  int*myp;  myp= new int[i]; ...如果你要这种动态数组的话,那就要先新建一个数组,把数存下来,在扩充,再放回去,但是我这里给你另一个方法,是bcb
  • “数组,真的不知道要怎么样才能学会……真的很难,还有什么三键录入,麻烦!” 这应该经常是新手抱怨的了,同时经常...这对新手获说是一件好事,下面小编就来好好聊聊这场意义的革新动态数组的出现,三键或成历...
  • 数组是什么?数组是一个能在变量中存储多个值的特殊变量。...关联数组-带有指定的键的数组,每个键关键一个值PHP数值数组有两种创建数值数组的方法:1、自动分配键值(键值从0开始):$a=array(12,32,23);2...
  • 使用malloc函数创建动态数组

    千次阅读 2019-11-04 10:27:07
    #include<stdio.h> #include<stdlib.h> //使用malloc函数动态创建一个数组 int main(){ /* malloc接收一个整型参数 malloc(20)代表申请20个字节... 但是内存了,还要说明用什么数据类型来解析 ...
  • 数据结构 定义 到目前为止,没有精确的定义,以下几种解释: 数据结构+算法=程序 以一定的方式,将信息组织在一起。 为什么学数据结 ...动态数组 实现: // #include "stdafx.h" #pragma once #include &l
  • 为什么我们要介绍动态数组,它有什么用?因为我们在写VBA程序的时候要存储的数据是多少,我们一般不能提前知道,所以很难定义数组的大小,如果定义小了存储不了数据,定义大了容易消耗内存。 动态数组的声明方式:...
  • 虽然我之前就是完全按照他讲的样子敲动态数组结构没敲出来,我也不知道为什么自己编译老通不过,要么就是wntdll未加载,按照百度的勾了什么符号加载也还是解决不了,要么就是无法解析的外部命令(我是vc2019)。...
  • 1.vector与数组的区别 ...vector相当于动态数组,比如 char str[100];只能存储100个字符。vector可以动态增长。 vector str(10,‘A’); //初始化为zhi包含10个’A’字符的数组 str.push_back(‘B’); // 现在dao
  • 实现动态扩容的方式很多,但是在数组的后面接上一段内存是明显不行的,我们需要做的就是重新申请一个更大容量的数组,这样才是可行的方法,但是问题又来了用什么方式来申请才能够最有效的扩容,我
  • // 动态开辟二维数组 #include #include using namespace std; class newTwoArray { public:  newTwoArray(){} newTwoArray(int r,int c);  int* newArray(); void setRC();  int getRC(); void ...
  • 一、什么是线性表 线性表是指零个或多个数据元素的有限序列,首先线性表是一个序列,除了第一个元素没有前排元素(前驱)、最后一个元素没有后排元素(后继),其他的元素每一个都自己的前驱以及后继。 顺序存储...
  • 那他们有什么区别和联系呢,下面来一起来说说:C语言表示字符串的两种方式,如下:首先,任何常量都将被放置到一个固定的内存区域,叫 .rodata 区,也叫常量区。因此上述代码中的 "abcde" 和 "uvxyz" 都被放置在这...
  • 数组

    2020-09-08 22:25:48
    什么用数组? 方便,可以一下定义多个相同类型的数据 数组的缺点: 1 一个数组只能定义一个数据类型 2 数组在创建时就被定义了长度,无法改变 数组的创建: 方式一 :动态初始化 声明: 类型[] 变量名; 初始化: 变量名=...
  • foreach的主要在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach元素的属性主要item,index,collection,open,separator,close。item表示集合中每一个元素进行迭代时的别名,index指定一个名字,...
  • —****** 1******—要实现什么函数呢?...先列出来:要用动态分配的内存的方式,来存放数组元素,且需要一个指针成员变量重载赋值 = 运算符重载括号 [] 运算符重载复制构造函数实现 push_back 和 ...
  • vector取代C-style的数组提起数组,大家想必都很熟悉,你可以索引和指针来操作数组,给程序设计带来了很大的灵活性。...有什么办法可以解决这些问题吗?你不用担心,下面我来给大家介绍一种方法:vector取代C-...
  • java数组

    2019-11-09 09:23:21
    1.为什么用数组 时候需要存储或处理一系列数据 2.什么时候用数组 当数据量很大时 3.当操作数组的时候,什么时候循环 当操作数组>=3的时候循环 4.怎么用数组 数组赋值:静态赋值和动态赋值 5.首先先了解...
  • 什么有动态内存管理 //没有动态内存分配之前我们掌握开辟的内存的方式: double a=10; //在栈上分配8个字节大小的空间 char ch[10]; //在栈上分配一段连续的空间 以上述方式开辟的内存一下特点: ■ 空间开辟...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,172
精华内容 468
关键字:

动态数组有什么用