【算法】C語言實現數組的動態分配


C語言實現數組的動態分配

作者:白寧超

2016年10月27日20:13:13

摘要:數據結構和算法對於編程的意義不言而喻,具有指導意義的。無論從事算法優化方向研究,還是大數據處理,亦或者網站開發APP開發雲雲。在求職過程中數據結構必然也是筆試的重點,面試的常客。基於此,系統梳理復習下數據結構和算法相關知識,其實核心為鏈表操作,串的匹配,樹的先序、中序、后序。排序的相關操作,查找相關操作,深度優先遍歷、廣度優先遍歷、哈弗曼樹、動態規划等。本節為開胃菜,數組的相關操作本文原創編著,轉載注明出處:C語言實現數組的動態分配

1 數組動態分配思想

數組是最常用的數據結構,在內存中連續存儲,可以靜態初始化(int a[2]={1,2}),可以動態初始化 malloc()。難點就是數組在刪除或者插入元素的時候,要移動元素的坐標不好確定。規律:

1.如果要在數組中第pos個位置插入一個元素(應該從后面開始移動)

for( i=cnu;i>=pos;i--)
pBase[i]=pBase[i-1];

2.刪除數組第pos位置的元素

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 完整案例

#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. 花括號內創建結構體屬性

例如:

/* 定義結構體 */
struct Arr{
	int len;//數組能存取的最大元素個數
	int cnu;//數組中當前元素個數
	int *pBase;//存儲指向數組的指針
};

 

初始化數組:

思路:

  1. 創建初始化函數,給數組分配長度malloc(sizeof(int)*len
  2. 指針地址為空,分配內存失敗
  3. 反之,數組長度為當前內存長度,數組當前位置為0

例如:

/*初始化數組*/
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. 判斷當前元素個數是否為空 
/*判斷數組是否為空,傳地址省內存4字節,傳結構體變量需要進行拷貝,12字節*/
bool isempty(struct Arr *pArray){
	if(0==pArray->cnu) return true;
	else return false;
}

判斷數組是否為滿:

  1. 創建判滿函數,結構體參數數組
  2. 判斷數組長度是否為當前元素長度 

例如:

/*判斷數組是否滿了*/
bool isfull(struct Arr *pArray){
  if(pArray->len==pArray->cnu)	return true;
  else return false;
}

向數組追加元素:

  1. 創建追加函數,結構體數組參數,元素值
  2. 注意判滿情況,反之循環輸入
  3. 數組當前指針地址賦值
  4. 數組指向下一個位置,自加

例如:

/*向數組追加元素*/
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. 遍歷數組輸出

例如:

/*顯示數組內容*/
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

例如:

/*向數組中插入元素,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. 指針向前指向,自減

例如:

/*刪除數組中的第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索引分別前進一步,直到跳出循環,程序結束

例如:

/*數組倒置*/
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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM