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) 可以直接根據下標找到內存位置
缺點:
- 事先必須知道數組的長度
- 插入刪除元素很慢
- 空間通常是有限制的
- 需要大塊連續的內存塊
- 插入刪除元素的效率很低
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為此結構體聲明的變量。
思路:
- 創建結構體記得關鍵字struct
- 花括號內創建結構體屬性
例如:
1
2
3
4
5
6
|
/* 定義結構體 */
struct
Arr{
int
len;
//數組能存取的最大元素個數
int
cnu;
//數組中當前元素個數
int
*pBase;
//存儲指向數組的指針
};
|
初始化數組:
思路:
- 創建初始化函數,給數組分配長度malloc(sizeof(int)*len
- 指針地址為空,分配內存失敗
- 反之,數組長度為當前內存長度,數組當前位置為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
3
4
5
|
/*判斷數組是否為空,傳地址省內存4字節,傳結構體變量需要進行拷貝,12字節*/
bool
isempty(
struct
Arr *pArray){
if
(0==pArray->cnu)
return
true
;
else
return
false
;
}
|
判斷數組是否為滿:
- 創建判滿函數,結構體參數數組
- 判斷數組長度是否為當前元素長度
例如:
1
2
3
4
5
|
/*判斷數組是否滿了*/
bool
isfull(
struct
Arr *pArray){
if
(pArray->len==pArray->cnu)
return
true
;
else
return
false
;
}
|
向數組追加元素:
- 創建追加函數,結構體數組參數,元素值
- 注意判滿情況,反之循環輸入
- 數組當前指針地址賦值
- 數組指向下一個位置,自加
例如:
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
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]插入元素
- 創建插入函數,結構體數組參數,位置參數,插入值參數
- 判斷插入位置是否越界,判斷數組是否滿
- 循環將pos位置開始的數組后移,移動范圍是從第pos個到第cnu個
- 循環將pos位置開始的數組后移,將值插入pos處
- 指向下一位且長度加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個元素:同時返回刪除的元素的值
- 創建插入函數,結構體數組參數,位置參數,插入值參數
- 判斷插入位置是否越界合法
- 獲取刪除的元素值
- 移動單位是從第pos+1個到cnu
- 指針向前指向,自減
例如:
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
;
}
}
|
數組倒置
- 創建倒置函數,判斷數組是否為空
- 三個變量進行交換,其中temp中間變量,ij分別指向數組首尾索引
- 循環數組,使前后索引交換位置
- 每一遍循環,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
;
}
|