一. 线性表是具有相同特性数据元素的有限序列。
二. 线性表的顺序表示和实现:
线性表的顺序表示指的是用一组地址连续的存储单元一次存储线性表的数据元素。换句话说,以元素在计算机内”物理位置相邻“来表示线性表中数据元素之间的逻辑关系。每一个数据元素的储存位置都和线性表的起始位置相差了一个和数据元素在线性表中的位序成正比的常数。
- 顺序表的优点:查找数据比较灵活,时间复杂度仅为O(1)。
- 顺序表的缺点:对顺序表进行添加、删除元素操作比较麻烦,需要移动大量的元素,对于有n个元素的顺序表,插入和删除元素的平均时间复杂度为O((n-1)/2)。
-
定义
#define ListInitSize 5 //线性表分配的初始容量 typedef struct{ int *elem; //储存空间基地址 int length; //当前长度 int ListSize; //当前分配的容量 }List;
我们用一个结构体来存储线性表,顺序线性表的结构体里面包括存储空间基地址、线性表当前的长度以及当前分配的容量。
-
创建线性表
int ListCreat(List *L){ //构造一个空的线性表 L->elem = (int *)malloc(ListInitSize*sizeof(int)); if(!L->elem) exit(-1); //存储分配失败 L->length = 0; //当前长度为0 L->ListSize = ListInitSize; //初始存储容量 return OK; }
因为C语言无法使用引用,但是有需要改变传入结构体的值,所以这个函数的入口参数定义为指针型,在调用函数时传入的为结构体的地址。
-
插入元素
int ListInsert(List *L, int x, int e){ //在线性表L的第x个位置前插入元素e int *temp=NULL, *q=NULL, *p=NULL; if(x<1 || x>L->length+1) return ERROR;//插入位置不合法 if(L->length+1 > L->ListSize){//重新分配内存 temp = (int *)realloc(L->elem, (L->ListSize+10)*sizeof(int)); if(!temp) exit(-1);//存储分配失败 L->ListSize += 10; L->elem = temp; } q = &(L->elem[x-1]); //获取需要插入元素的地址 for(p=&(L->elem[L->length-1]); p>=q; --p) *(p+1)= *p; //后面元素全部右移 *q = e; L->length += 1; return OK; }
-
删除元素
int ListDel(List *L, int x, int *e){ //在线性表L中删除第x个元素并返回数值 int *p=NULL, *q=NULL; if(x<1 || x>L->length) return ERROR; //删除位置不合法 *e = L->elem[x-1]; //返回删除的值 for(q=&(L->elem[x]); q<=&(L->elem[L->length-1]); q++){ *(q-1) = *q; //后面元素全部左移 } L->length -= 1; //表长减一 return OK; //操作完成 }
-
验证
int main(int argc, char *argv[]) { List L; int i,j; //创建线性表 ListCreat(&L); printf("长度 %d\t容量 %d\n",L.length,L.ListSize); //循环填充1-10 for(i=0;i<10;i++){ ListInsert(&L, 1, 10-i); } //查看线性表中全部值 for(i=0;i<L.length;i++){ printf("%d ",L.elem[i]); } //删除掉第五个后查看全部值 ListDel(&L, 5, &j); printf("\n删掉的元素值为%d\n删除后为:",j); for(i=0;i<L.length;i++){ printf("%d ",L.elem[i]); } return 0; }
-
输出结果
经过验证函数正确有效。