初始化执行期间通过malloc函数为数组申请空间,程序运行期间若空间不够可通过realloc函数在保留原存储值的前提下为数组申请更大的连续存储的空间。 源代码如下:
#include<stdio.h> #include<stdlib.h> #define initSize 1000 #define incSize 500 //增大顺序表存储空间时每次的增长值 #define OVERFLOW 9999 #define ERROR -1 #define EMPTY -2 typedef int eleType; typedef struct{ eleType *Delem; int length; }DList; // 函数申明 void initList(DList *L); void insertList(DList *L,int i,eleType e); int listLength(DList L); int getElem1(DList L,int i); void getElem2(DList L,int i,eleType *e); int locateElem(DList L,int e); void listDelete(DList *L,int i,eleType *e); void printList(DList L); int emptyList(DList L); void destroyList(DList *L); int main(){ DList L; initList(&L); int e; int i; int o; for(i=1;i<5;i++){ insertList(&L,i,i); } printList(L); printf("Hello!\n"); int m = listLength(L); printf("顺序表的长度:\t%d\n",m); insertList(&L,2,22); printList(L); printf("第二个元素:%d\t\n",getElem1(L,1)); getElem2(L,2,&e); printf("第三个元素:%d\t\n",e); printf("元素4的index=%d\n",locateElem(L,4)); listDelete(&L,3,&o); printf("删除的元素值:%d\n",o); printList(L); printf("%d\n",emptyList(L)); destroyList(&L); return 0; } // 初始化链表 void initList(DList *L){ L->Delem = (eleType *)malloc(initSize *sizeof(eleType)); if(!L->Delem) exit(OVERFLOW); L->length = 0; return; } void insertList(DList *L,int i,eleType e){ if(L->length == initSize){ eleType *p; p = (eleType *)realloc(L->Delem,(initSize + incSize)*sizeof(eleType)); if(!p){ // 未分配成功 exit(OVERFLOW); } L->Delem = p; // L->Delem 指向新申请的存储空间 L->length += incSize; //表长修改为新的存储空间可存放数据元素个数 } // if(i<1 || i>L->length) // exit(ERROR); int j; for(j=L->length-1;j>=i-1;j--) L->Delem[j+1] = L->Delem[j]; //从表尾开始插入位置,数据元素依次后移动一个位置 L->Delem[i-1] = e; L->length++; return; } // 求线性表的长度 int listLength(DList L){ return L.length; } // 获取线性表的第i个元素 int getElem1(DList L,int i){ if(i<0 || i>L.length) exit(ERROR); return L.Delem[i]; } // 获取线性表的第i个元素 void getElem2(DList L,int i,eleType *e){ if(i<0 || i>L.length) exit(ERROR); *e = L.Delem[i]; return; } // 确定元素e是线性表中的第几个元素 int locateElem(DList L,int e){ int i; for(i=0;i<L.length;i++) if(L.Delem[i]==e) break; if(i!=L.length) return i; else return 0; } //删除线性表中的第i个元素,将其放在变量e中 void listDelete(DList *L,int i,eleType *e){ if(L->length==0){ exit(EMPTY); } if(i<1 || i>L->length) exit(ERROR); *e = L->Delem[i-1]; // 线性表中的第i个元素存放于变量e中 int j; for(j=i-1; j<L->length-1; j++) { //从第i个数据元素开始,依次将后面的元素前移一个位置 L->Delem[j] = L->Delem[j+1]; } L->length--; return; } //遍历线性表 void printList(DList L){ int i; for( i=0;i<L.length;i++){ printf("%d\t",L.Delem[i]); } printf("\n"); } //判断线性表为空,前提条件是线性表存在 int emptyList(DList L){ if(L.length > 0) return 1; return 0; } //销毁线性表 void destroyList(DList *L){ if(!L->Delem) //没有可销毁的内容 exit(ERROR); free(L->Delem); L->length =0; }按照我们期望的运行结果 值得思考的是在insertList(DList *L,int i,eleType e)函数中有个完备性检查未能实现:
if(i<1 || i>L->length) exit(ERROR);通过静态分配和动态分配对比可知,共同点都是使用数组构造,逻辑基本相同,不同的就是,动态分配在原数组满了的情况下可以扩充,而静态的是数组存满就不能扩充了。大家可以思考两种分配方式中所用到的空间复杂度和时间复杂度。