数组的动态分配

C语言实现数组的动态分配

摘要:数据结构和算法对于编程的意义不言而喻,具有指导意义的。无论从事算法优化方向研究,还是大数据处理,亦或者网站开发APP开发云云。在求职过程中数据结构必然也是笔试的重点,面试的常客。基于此,系统梳理复习下数据结构和算法相关知识,其实核心为链表操作,串的匹配,树的先序、中序、后序。排序的相关操作,查找相关操作,深度优先遍历、广度优先遍历、哈弗曼树、动态规划等。本节为开胃菜,数组的相关操作(本文原创编著,转载注明出处:C语言实现数组的动态分配

1 数组动态分配思想

数组是最常用的数据结构,在内存中连续存储,可以静态初始化(int a[2]={1,2}),可以动态初始化 malloc()。难点就是数组在删除或者插入元素的时候,要移动元素的坐标不好确定。规律:

1.如果要在数组中第pos个位置插入一个元素(应该从后面开始移动)


1

2

for( i=cnu;i>=pos;i--)

pBase[i]=pBase[i-1];

2.删除数组第pos位置的元素


1

2

for(i=pos+1;i<=cnu;i--)

pBase[i-2]=pBase[i-1];

使用malloc动态分配内存并将返回值赋给整形指针

int pBase=(int *)malloc(sizeof(int)len);//分配4*len字节长度的内存

这是pBase可以指向数组中的第一个元素,可以作为数组变量名称使用。

2 数组的优缺点

优点:

存取速度快 o(1) 可以直接根据下标找到内存位置

缺点:

  1. 事先必须知道数组的长度
  2. 插入删除元素很慢
  3. 空间通常是有限制的
  4. 需要大块连续的内存块
  5. 插入删除元素的效率很低

3 完整案例


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

#include<stdio.h>

#include<malloc.h>

#include<stdbool.h>

/* 定义结构体 */

struct Arr{

    int len;//数组能存取的最大元素个数

    int cnu;//数组中当前元素个数

    int *pBase;//存储指向数组的指针

};

/*初始化数组*/

void init_Arr(struct Arr *pArray,int len){

    pArray->pBase=(int*)malloc(sizeof(int)*len);//分配4*len字节长度的内存

    if(NULL== pArray->pBase){

        printf("动态分配内存失败\n");

    }else{

        pArray->len=len;

        pArray->cnu=0;

        printf("动态分配内存成功 %d \n",pArray->len);

    }

}

/*判断数组是否为空,传地址省内存4字节,传结构体变量需要进行拷贝,12字节*/

bool isempty(struct Arr *pArray){

    if(0==pArray->cnu) return true;

    else return false;

}

/*判断数组是否满了*/

bool isfull(struct Arr *pArray){

  if(pArray->len==pArray->cnu)    return true;

  else return false;

}

/*显示数组内容*/

void show_Arr(struct Arr *pArray){

    if(isempty(pArray))    printf("数组为空!\n");

    else{

    for(int i=0; i<pArray->cnu;i++){

        printf("%d \t\t %d \t\t %d \n",pArray->pBase[i],pArray->cnu,pArray->len);

    }

    printf("------------------------------------\n");

    }

}

/*向数组追加元素*/

bool append(struct Arr *pArray,int val){

    if(isfull(pArray)){

        printf("数组已经满了!\n");

        return false;

    }else{

            pArray->pBase[pArray->cnu]=val;

            pArray->cnu++;

    }

}

/*向数组中插入元素,pos为数组中第几个位置,pos=3就是向a[2]插入元素*/

bool insert(struct Arr *pArray,int pos,int val){

    if(pos<1||pos>pArray->len+1){

        printf("插入的位置输入的不合法\n");

        return false;

    }

    if(isfull(pArray)){

        printf("数组已经满了,插入失败!\n");

        return false;

    }

    else{

        //printf("数组 %d \n",pArray->cnu);

        for(int i=pArray->cnu;i>=pos;i--){//循环将pos位置开始的数组后移

            pArray->pBase[i]=pArray->pBase[i-1];

        }

        pArray->pBase[pos-1]=val;

        pArray->cnu++;

        pArray->len++;

        return true;

    }

}

/*删除数组中的第pos个元素,同时返回删除的元素的值*/

bool delete(struct Arr *pArray,int pos,int *val){

    if(pos<1||pos>pArray->cnu){

        printf("删除失败,位置不合法\n");

        return false;

    }

    if(isempty(pArray)){

        printf("数组已经空,删除失败!\n");

        return false;

    }

    else{

        *val=pArray->pBase[pos-1];

        for(int i=pos+1;i<=pArray->cnu;i++){

            pArray->pBase[i-2]=pArray->pBase[i-1];

        }

        pArray->cnu--;

        return true;

    }

}

/*数组倒置*/

bool inverse(struct Arr *pArray){

    if(isempty(pArray)){

        printf("倒置失败,因数组为空");

        return false;

    }

    else{

        int i=0,j=pArray->cnu-1,temp;

        while(i<j){

            temp=pArray->pBase[i];

            pArray->pBase[i]=pArray->pBase[j];

            pArray->pBase[j]=temp;

            i++;

            j--;

        }

    }

    return true;

}

int main(){

    struct Arr arr;

    init_Arr(&arr,20);

    append(&arr,1);

    append(&arr,2);

    append(&arr,3);

    append(&arr,4);

    append(&arr,5);

    show_Arr(&arr);

    insert(&arr,2,88);

    show_Arr(&arr);

    int val;

    delete(&arr,1,&val);

    show_Arr(&arr);

    printf("删除了 %d\n",val);

    inverse(&arr);

    show_Arr(&arr);

    return 0;

}

 

4 运行结果



Success time: 0 memory: 2300 signal:0

动态分配内存成功 20
1 		 5 		 20
2 		 5 		 20
3 		 5 		 20
4 		 5 		 20
5 		 5 		 20
------------------------------------
1 		 6 		 21
88 		 6 		 21
2 		 6 		 21
3 		 6 		 21
4 		 6 		 21
5 		 6 		 21
------------------------------------
88 		 5 		 21
2 		 5 		 21
3 		 5 		 21
4 		 5 		 21
5 		 5 		 21
------------------------------------
删除了 1
5 		 5 		 21
4 		 5 		 21
3 		 5 		 21
2 		 5 		 21
88 		 5 		 21
------------------------------------

5 实例解析

结构体:结构体(struct)指的是一种数据结构,是C语言中聚合数据类型的一类。 结构体可以被声明为变量、指针或数组等,用以实现较复杂的数据结构。结构体的定义如下所示,

struct tag { member-list } variable-list ;

struct为结构体关键字,tag为结构体的标志,member-list为结构体成员列表,其必须列出其所有成员;variable-list为此结构体声明的变量。

思路:

  1. 创建结构体记得关键字struct
  2. 花括号内创建结构体属性

例如:


1

2

3

4

5

6

/* 定义结构体 */

struct Arr{

    int len;//数组能存取的最大元素个数

    int cnu;//数组中当前元素个数

    int *pBase;//存储指向数组的指针

};

初始化数组:

思路:

  1. 创建初始化函数,给数组分配长度malloc(sizeof(int)*len
  2. 指针地址为空,分配内存失败
  3. 反之,数组长度为当前内存长度,数组当前位置为0

例如:


1

2

3

4

5

6

7

8

9

10

11

/*初始化数组*/

void init_Arr(struct Arr *pArray,int len){

    pArray->pBase=(int*)malloc(sizeof(int)*len);//分配4*len字节长度的内存

    if(NULL== pArray->pBase){

        printf("动态分配内存失败\n");

    }else{

        pArray->len=len;

        pArray->cnu=0;

        printf("动态分配内存成功 %d \n",pArray->len);

    }

}

判断数组是否为空:

  1. 创建判空函数,结构体参数数组
  2. 判断当前元素个数是否为空

1

2

3

4

5

/*判断数组是否为空,传地址省内存4字节,传结构体变量需要进行拷贝,12字节*/

bool isempty(struct Arr *pArray){

    if(0==pArray->cnu) return true;

    else return false;

}

判断数组是否为满:

  1. 创建判满函数,结构体参数数组
  2. 判断数组长度是否为当前元素长度

例如:


1

2

3

4

5

/*判断数组是否满了*/

bool isfull(struct Arr *pArray){

  if(pArray->len==pArray->cnu)    return true;

  else return false;

}

向数组追加元素:

  1. 创建追加函数,结构体数组参数,元素值
  2. 注意判满情况,反之循环输入
  3. 数组当前指针地址赋值
  4. 数组指向下一个位置,自加

例如:


1

2

3

4

5

6

7

8

9

10

/*向数组追加元素*/

bool append(struct Arr *pArray,int val){

    if(isfull(pArray)){

        printf("数组已经满了!\n");

        return false;

    }else{

        pArray->pBase[pArray->cnu]=val;

        pArray->cnu++;

    }

}

  

显示数组内容

  1. 创建显示函数,结构体数组参数
  2. 注意判空情况,反之循环输入
  3. 遍历数组输出

例如:


1

2

3

4

5

6

7

8

9

10

/*显示数组内容*/

void show_Arr(struct Arr *pArray){

    if(isempty(pArray))    printf("数组为空!\n");

    else{

    for(int i=0; i<pArray->cnu;i++){

        printf("%d \t\t %d \t\t %d \n",pArray->pBase[i],pArray->cnu,pArray->len);

    }

    printf("------------------------------------\n");

    }

}

  

向数组中插入元素:pos为数组中第几个位置,pos=3就是向a[2]插入元素

  1. 创建插入函数,结构体数组参数,位置参数,插入值参数
  2. 判断插入位置是否越界,判断数组是否满
  3. 循环将pos位置开始的数组后移,移动范围是从第pos个到第cnu个
  4. 循环将pos位置开始的数组后移,将值插入pos处
  5. 指向下一位且长度加1

例如:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

/*向数组中插入元素,pos为数组中第几个位置,pos=3就是向a[2]插入元素*/

bool insert(struct Arr *pArray,int pos,int val){

    if(pos<1||pos>pArray->len+1){

        printf("插入的位置输入的不合法\n");

        return false;

    }

    if(isfull(pArray)){

        printf("数组已经满了,插入失败!\n");

        return false;

    }

    else{

        //printf("数组 %d \n",pArray->cnu);

        for(int i=pArray->cnu;i>=pos;i--){//循环将pos位置开始的数组后移

            pArray->pBase[i]=pArray->pBase[i-1];

        }

        pArray->pBase[pos-1]=val;

        pArray->cnu++;

        pArray->len++;

        return true;

    }

}

  

删除数组中的第pos个元素:同时返回删除的元素的值

  1. 创建插入函数,结构体数组参数,位置参数,插入值参数
  2. 判断插入位置是否越界合法
  3. 获取删除的元素值
  4. 移动单位是从第pos+1个到cnu
  5. 指针向前指向,自减

例如:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

/*删除数组中的第pos个元素,同时返回删除的元素的值*/

bool delete(struct Arr *pArray,int pos,int *val){

    if(pos<1||pos>pArray->cnu){

        printf("删除失败,位置不合法\n");

        return false;

    }

    if(isempty(pArray)){

        printf("数组已经空,删除失败!\n");

        return false;

    }

    else{

        *val=pArray->pBase[pos-1];

        for(int i=pos+1;i<=pArray->cnu;i++){

            pArray->pBase[i-2]=pArray->pBase[i-1];

        }

        pArray->cnu--;

        return true;

    }

}

  

数组倒置

  1. 创建倒置函数,判断数组是否为空
  2. 三个变量进行交换,其中temp中间变量,ij分别指向数组首尾索引
  3. 循环数组,使前后索引交换位置
  4. 每一遍循环,ij索引分别前进一步,直到跳出循环,程序结束

例如:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

/*数组倒置*/

bool inverse(struct Arr *pArray){

    if(isempty(pArray)){

        printf("倒置失败,因数组为空");

        return false;

    }

    else{

        int i=0,j=pArray->cnu-1,temp;

        while(i<j){

            temp=pArray->pBase[i];

            pArray->pBase[i]=pArray->pBase[j];

            pArray->pBase[j]=temp;

            i++;

            j--;

        }

    }

    return true;

}

时间: 2024-10-17 07:36:23

数组的动态分配的相关文章

C++中二维数组的动态分配

作者:   来源:csdn博客   公布者:admin 时间:2009-04-23 13:55:03   点击:115 C++中一维数组的动态分配十分经常使用,但C++刚開始学习的人可能非常少想过要使用动态分配的二维数组,或者自觉得二维数组就是这样分配的(至少我自己開始的时候就这样觉得):int m=2, n=3; int** array2D=new int[m][n];.这全然是我们写多了像int n=4; int* array=new int[n];这种语句留下的后遗症,纯粹是由于惯性太大刹

C++ 二维数组/多维数组的动态分配(new)和释放(delete)

1. 一维数组 对于简单的一维数组动态内存分配和释放,如下: int *array1D;//假定数组长度为m //动态分配空间 array1D = new int [m]; //释放 delete [] array1D; 2. 二维数组 二维数组的动态分配和释放 //假定数组第一维长度为m, 第二维长度为n //动态分配空间 <pre name="code" class="cpp">int **array2D<span style="fo

二维数组的动态分配(new)、初始化(memset)和撤销(delete)

来自http://blog.csdn.net/maverick1990/article/details/22829135 一维数组 动态分配,int *array = new int[10] 初始化,memset(array,0,sizeof(array)); 撤销,delete[] array 二维数组m行n列 int **d; d = new int *[10]; for(int i =0;i<10;i++){ d[i] = new int[5] } 先分配一个10单元的数组指针的指针的首地

C++内存分配及变长数组的动态分配

//------------------------------------------------------------------------------------------------ 第一部分 C++内存分配 //------------------------------------------------------------------------------------------------ 一.关于内存 1.内存分配方式 内存分配方式有三种: (1)从静态存储区域分配

【转载】二维数组的动态分配和参数传递

本篇随笔为转载,原贴地址:http://www.cnblogs.com/bigshow/archive/2009/01/03/1367661.html. 1. C语言动态分配二维数组 (1)已知第二维 Code-1 char (*a)[N];//指向数组的指针 a = (char (*)[N])malloc(sizeof(char *) * m); printf("%d\n", sizeof(a));//4,指针 printf("%d\n", sizeof(a[0]

比较C/C++和Delphi中的字符串和字符数组(数组和动态分配内存的情况)

本文所讲解的只是从其中一个方面来看待进行的总结,所以有必要结合<Delphi字符串与字符数组之间的转换(初始化的重要性)>等文章进行更全面的了解,会从更多方面来理解字符串.内存.类型转换 C/C++中的字符串.字符数组.字符指针分配的内存空间 我们知道在C/C++中,我们可以这样理解字符串和字符数组 1)字符串,就是一个以 '\0' 结尾的字符数组 2)字符数组,包括字符串,但是不一定要以 '\0' 结尾,如果不是以'\0' 结尾,那么就不能当做字符串使用 在C/C++中,使用字符串可以通过数

二维数组的动态分配

参见:http://blog.csdn.net/handsome_926/article/details/8233744 参见:http://blog.csdn.net/gaohuaid/article/details/10822851 32位(bit)和64位(bit)系统的指针占的内存不一样,注意B与b不同,B是Byte(字节),b是bit(位) 1GB=1024MB,1MB=1024KB,1KB=1024B,1B=8bit 在32位的系统中,所有指针都占4 bytes.cpu决定内存的编址

C/C++上二维数组的两种动态分配内存方法

最近在看一个程序的源代码的时候了解到了二维数组的动态分配空间以及释放的方法,在此记录. 一.二维数据的内存空间动态分配 方法一: void malloc2D_1(int **&a) { a = new int*[xDim]; for(int i=0;i<xDim;i++) a[i] = new int[yDim]; assert(a!=NULL); } int main() { int **arr = NULL; malloc2D_1(arr); } 首先arr是一个二级指针,为arr分配x

动态数组索引越界问题

1.在C++中,可以采用几种不同的方法创建一个某种类型T的对象的数组.3种常用的方法如下: #define N 10 //数组的长度N在编译时已知 T static_array[10]; int n = 20; //数组的长度n是在运行时计算的 T* dynamic_array = new T[n]; std::vector<T> vector_array; //数组的长度可以在运行时进行修改 当然,我们仍然可以使用calloc()和malloc()函数,并且这样的程序仍然能够通过编译并顺利运