C語言多維數組數據結構的實現詳解

數據結構之多維數組

定義結構體

typedef struct {

	ElemType* base;//數組元素基址(數組基址)
	int dim;//數組維數
	int* bounds;//數組維界基址(存放各位長度信息)
	int* constants;//數組映象函數常量基址
}Array;

各基本操作函數原型說明

(1)創建數組

//若函數參數合法,則構建數組A
Status InitArray(Array* A, int dim, ...);

(2)銷毀數組

//銷毀數組
Status DestroyArray(Array* A);

(3)數組的定位

//獲取元素位置(數組定位)
Status LocateArray(Array A, va_list ap, int* offset);

(4)數組元素的賦值

//A為n維數組,e為元素變量,隨後是n個下標值
//若下標不超界,則將e的值賦給所指定的A的元素(賦值)
Status SetArray(Array* A, ElemType e, ...);

(5)獲取數組元素

//A為n維數組,e為元素變量,隨後是n個下標值
//若下標不超界,則將e賦值為所指定的A的元素(獲取)
Status GetValue(ElemType* e, Array A, ...);

各基本操作的具體實現

(1)創建數組函數實現

//創建多維數組
Status InitArray(Array* A, int dim, ...) {
	if (dim <1 || dim>MAX_ARRAY_DIM) return ERROR;//參數不合法
	A->dim = dim;
	A->bounds = (int*)malloc(sizeof(int) * dim);
	if (!A->bounds) return OVERFLOW;//分配內存失敗
	//若各維長度合法,則存入A.bounds,並求出A的元素總數elemtotal
	int elemtotal = 1;
	va_list ap;
	va_start(ap, dim);
	for (int i = 0; i < dim; ++i) {
		A->bounds[i] = va_arg(ap, int);
		if (A->bounds[i] < 0)return UNDERFLOW;
		elemtotal *= A->bounds[i];
	}
	va_end(ap);
	//為數組分配內存空間內
	A->base = (ElemType*)malloc(sizeof(ElemType) * elemtotal);
	if (!A->base) return OVERFLOW;//分配內存失敗
	//求映像函數Ci,並存入A.constants[i-1],i = 1,...,dim;
	A->constants = (int*)malloc(sizeof(int) * dim);
	if (!A->constants) return OVERFLOW;//分配內存失敗
	A->constants[dim - 1] = 1;
	for (int i = dim - 2; i >= 0; --i) {
		A->constants[i] = A->bounds[i + 1] * A->constants[i + 1];
	} 
	return OK;
}

(2)銷毀數組函數實現

//銷毀數組
Status DestroyArray(Array* A) {
	if (!A->base) return ERROR;
	free(A->base);
	A->base = NULL;
	if (!A->bounds) return ERROR;
	free(A->bounds);
	A->bounds = NULL;
	if (!A->constants) return ERROR;
	free(A->constants);
	A->constants = NULL;
	return OK;
}

(3)數組定位函數實現

//數組的定位
Status LocateArray(Array A, va_list ap, int* offset) {
	int i, instand;
	//若ap指示的元素下標合理,則求出元素相對位置,返回到offset
	*offset = 0;
	for (i = 0; i < A.dim; i++) {
		instand = va_arg(ap, int);
		if (instand < 0 || instand > A.bounds[i]) {
		//	printf("instand = %d,定位失敗\n",instand);//調試代碼
			return ERROR;
		}
		*offset += A.constants[i] * instand;
	}
	return  OK;
}

(4)數組元素賦值函數實現

//數組賦值
Status SetArray(Array *A, ElemType e, ...) {
	va_list ap;
	int offset;
	va_start(ap, e);
	if (LocateArray(*A, ap, &offset) == ERROR) return ERROR;
	va_end(ap); 
	*(A->base + offset) = e;
	return OK;
}

(5)取出數組元素函數實現

//獲取數組元素的值,並用E返回
Status GetValue(ElemType* e, Array A, ...) {
	va_list ap;
	int offset;
	va_start(ap, A);
	if (LocateArray(A, ap, &offset) == ERROR) return ERROR;
	va_end(ap);
	*e = *(A.base + offset);
	return OK;
}

測試分析

創建

創建一個二維數組,其第一維長度為4,第二維長度為3。

測試代碼:

運行結果:

銷毀

將結構體A的地址傳入到DestroyArray函數中,執行操作。

測試代碼:

運行結果:

數組元素賦值

定義二維數組B[4][3],通過SetArray函數將其值賦給數組A,通過遍歷輸出A中元素的值,則可以判斷出賦值是否準確。

測試代碼:

運行結果:

取出數組元素

測試代碼:

運行結果:

思考與小結

1、 對數組的再認識

存儲器的結構是一維線性的結構,數組是多維的結構。如果要將一個多維的結構放在一個一維的存儲單元裡,就必須先將多維的數組轉換成一個一維的線性序列,才能將其放在存儲器當中。數組的存儲方式主要有兩種:一張是以行序為主的存儲方式,另外一種是以列序為主的存儲方式。

2、調試過程中遇到的問題及解決方案

1、兩次編譯報錯

①錯誤信息:va_start argument must not have reference type and must not be parenthesized;

va_start函數的運用問題,函數原型:void va_start(va_list ap,parmN);報錯原因為參數不正確。查看c語言開發手冊,得出原因。

ap 一個va_list類型的實例

Prmhn 第一個變量參數前的命名參數

②錯誤信息:*LNK2019 無法解析的外部符號 “int __cdecl SetArray(struct Array ,int,int,…)” (?SetArray@@YAHPAUArray@@HHZZ),函數 _main 中引用瞭該符號

此錯誤信息為,找的到定義卻又未找到實現的函數,故需將函數實現後才能調用,同時註意參數的對應,避免出現以上問題。

2、運行時報錯

運行時報錯,數據訪問出現問題。通過檢查報錯信息的前後語句,發現在訪問數組的時候忘記i+1,導致i走到-1形成錯誤原因。

3、運行結果出錯

運行結果出現瞭地址與數值都輸出的情況,通過調試,發現第一次進入LocateArray函數之後,函數返回瞭ERROR,通過打印語句檢查,函數確實進入瞭判斷語句內,返回ERROR;

表明參數不準確或者函數判斷語句不正確,由於數值為自己控制的,故參數不準確的可能性較小,仔細分析瞭參數臨界以及函數邏輯,將判斷參數的條件改成正確判斷語句。得到正確的結果。

3、算法的時間復雜度分析

InitArray函數的時間復雜度為O(n);

DestroyArray函數的時間復雜度為O(1);

LocateArray函數的時間復雜度為O(n);

SetArray函數的時間復雜度為O(n);

GetArray函數的時間復雜度為O(n);

SetArray函數和GetArray函數的時間復雜度主要受LocateArray函數影響。

總結

到此這篇關於C語言多維數組數據結構實現的文章就介紹到這瞭,更多相關C語言多維數組數據結構內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: