//向一个线性表list的pos位置处插入新元素node int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) { int ret = 0; //1 缓存下来 进行操作 TSeqList *tmp = NULL; if (NULL == list || NULL == node || pos < 0) { ret = -1; printf("func err NULL == list || NULL == node || pos < 0:%d\t", ret); return ret; } tmp = (TSeqList *)list; //注意1:线性表长度应该小于等于数组的长度 if (tmp->length >=tmp->capacity) { ret = -2; printf("func err tmp->length >=tmp->capacity:%d\t", ret); return ret; } //注意2:容错修正 假设容量为20,此时线性表长度为6,pos却为10,这个时候可以做容错修正,直接修正为尾插法 if (pos > tmp->length) { pos = tmp->length; } //2 元素后移 int i; for ( i = tmp->length; i > pos; i--) { //t[3]=t[2]; tmp->node[i] = tmp->node[i-1];//后移 } //3 空出位置 插入新结点 tmp->node[i] = (unsigned int)node; //4 线性表长度+1 tmp->length++; return 0; }
//删除一个线性表list的pos位置处的元素 返回值为被删除的元素,NULL表示删除失败 SeqListNode* SeqList_Delete(SeqList* list, int pos) { int ret = 0; //1 缓存下来 进行操作 TSeqList *tmp = NULL; TSeqList *Deletemp = NULL; if (NULL == list || pos < 0) { ret = -1; printf("func err NULL == list || pos < 0:%d\t", ret); return NULL; } tmp = (TSeqList *)list; Deletemp = (SeqListNode *)tmp->node[pos];//缓存下来要删除的元素 //2 元素前移 for (int i = pos + 1; i < tmp->length; i++) { //t[1]=t[2] tmp->node[i - 1] = tmp->node[i]; } //3 删除元素后 线性表长度减1 tmp->length--; return Deletemp; }
线性表顺序存储设计与实现详细代码如下:
//线性表顺序存储设计与实现测试框架 //SeqList.h #ifndef _SEQLIST_H_ #define _SEQLIST_H_ typedef void SeqList; typedef void SeqListNode; /* 这两句话意思: C语言里面的typedef,字面上理解就是类型的定义,也就是给内置的或自定义的数据类型重新命名 typedef void SeqList; 等价于下面void* ===》SeqList* typedef void SeqListNode;下面代码SeqListNode* 等价于void * typedef void SeqList; 给void起别名为 SeqList typedef void SeqListNode; 这样做是为了使用者方便阅读, SeqList* SeqList_Create(int capacity); //这样一看返回值就知道是返回值是链表 void * SeqList_Create(int capacity); //如果这样,使用者一看只知道是返回指针,不知道具体的,可读性很差 所以才会给void起别名,封装好的底层函数,提供给使用者使用,使用者会给容易懂 */ //创建并且返回一个空的线性表 SeqList* SeqList_Create(int capacity); //销毁一个线性表list void SeqList_Destroy(SeqList* list); //将一个线性表list中的所有元素清空, 线性表回到创建时的初始状态 void SeqList_Clear(SeqList* list); //返回一个线性表list中的所有元素个数 int SeqList_Length(SeqList* list); //返回一个线性表list中的容量 int SeqList_Capacity(SeqList* list); //向一个线性表list的pos位置处插入新元素node int SeqList_Insert(SeqList* list, SeqListNode* node, int pos); //获取一个线性表list的pos位置处的元素 SeqListNode* SeqList_Get(SeqList* list, int pos); //删除一个线性表list的pos位置处的元素 返回值为被删除的元素,NULL表示删除失败 SeqListNode* SeqList_Delete(SeqList* list, int pos); #endif //
//SeqList.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "SeqList.h" //在结构体中套一级指针 typedef struct _tag_SeqList { int length;//线性表的长度 int capacity;//数组的长度-存放线性表的存储空间的长度 unsigned int *node;//链表需要有内存空间存储装元素-根据容量来分配内存空间-需要动态分配内存空间 }TSeqList; //创建并且返回一个空的线性表 SeqList* SeqList_Create(int capacity) { int ret = 0; //1 线性表申请动态内存空间 TSeqList *tmp = NULL; tmp = (TSeqList *)malloc(sizeof(TSeqList)); if (NULL == tmp) { ret = -1; printf("func err malloc:%d\t",ret); return NULL; } memset(tmp,0,sizeof(TSeqList));//让开辟的内存 完成线性表初始化 //2 根据容量分配内存大小 tmp->node = (unsigned int )malloc(sizeof(unsigned int *)*capacity); if (NULL == tmp->node) { ret = -2; printf("func err malloc:%d\t", ret); return NULL; } tmp->capacity = capacity; tmp->length = 0; return tmp; } //销毁一个线性表list //小心先开辟内存空间的后释放 void SeqList_Destroy(SeqList* list) { int ret = 0; //1 缓存下来 进行操作 TSeqList *tmp = NULL; if (NULL == list) { ret = -1; printf("func err SeqList_Destroy:%d\t", ret); } tmp = (TSeqList *)list; //先申请 后释放 if (tmp->node!=NULL) { free(tmp->node); } free(tmp); } //将一个线性表list中的所有元素清空, 线性表回到创建时的初始状态 void SeqList_Clear(SeqList* list) { int ret = 0; //1 缓存下来 进行操作 TSeqList *tmp = NULL; if (NULL == list) { ret = -1; printf("func err SeqList_Clear:%d\t", ret); } tmp = (TSeqList *)list; tmp->length = 0; memset(tmp->node, 0, tmp->capacity * sizeof(unsigned int *));//重新将线性表中创建的结点初始化 } //返回一个线性表list中的所有元素个数 int SeqList_Length(SeqList* list) { int ret = 0; //1 缓存下来 进行操作 TSeqList *tmp = NULL; if (NULL == list) { ret = -1; printf("func err SeqList_Length:%d\t", ret); return ret; } tmp = (TSeqList *)list; return tmp->length; } //返回一个线性表list中的容量 int SeqList_Capacity(SeqList* list) { int ret = 0; //1 缓存下来 进行操作 TSeqList *tmp = NULL; if (NULL == list) { ret = -1; printf("func err SeqList_Capacity NULL == list:%d\t", ret); return ret; } tmp = (TSeqList *)list; return tmp->capacity; } //向一个线性表list的pos位置处插入新元素node int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) { int ret = 0; //1 缓存下来 进行操作 TSeqList *tmp = NULL; if (NULL == list || NULL == node || pos < 0) { ret = -1; printf("func err NULL == list || NULL == node || pos < 0:%d\t", ret); return ret; } tmp = (TSeqList *)list; //注意1:线性表长度应该小于等于数组的长度 if (tmp->length >=tmp->capacity) { ret = -2; printf("func err tmp->length >=tmp->capacity:%d\t", ret); return ret; } //注意2:容错修正 假设容量为20,此时线性表长度为6,pos却为10,这个时候可以做容错修正,直接修正为尾插法 if (pos > tmp->length) { pos = tmp->length; } //2 元素后移 int i; for ( i = tmp->length; i > pos; i--) { //t[3]=t[2]; tmp->node[i] = tmp->node[i-1];//后移 } //3 空出位置 插入新结点 tmp->node[i] = (unsigned int)node; //4 线性表长度+1 tmp->length++; return 0; } //获取一个线性表list的pos位置处的元素 SeqListNode* SeqList_Get(SeqList* list, int pos) { int ret = 0; //1 缓存下来 进行操作 TSeqList *tmp = NULL; if (NULL == list || pos < 0) { ret = -1; printf("func err NULL == list || pos < 0:%d\t", ret); return NULL; } tmp = (TSeqList *)list; tmp = (SeqListNode *)tmp->node[pos]; return tmp; } //删除一个线性表list的pos位置处的元素 返回值为被删除的元素,NULL表示删除失败 SeqListNode* SeqList_Delete(SeqList* list, int pos) { int ret = 0; //1 缓存下来 进行操作 TSeqList *tmp = NULL; TSeqList *Deletemp = NULL; if (NULL == list || pos < 0) { ret = -1; printf("func err NULL == list || pos < 0:%d\t", ret); return NULL; } tmp = (TSeqList *)list; Deletemp = (SeqListNode *)tmp->node[pos];//缓存下来要删除的元素 //2 元素前移 for (int i = pos + 1; i < tmp->length; i++) { //t[1]=t[2] tmp->node[i - 1] = tmp->node[i]; } //3 删除元素后 线性表长度减1 tmp->length--; return Deletemp; }
//线性表顺序存储设计与实现测试框架 //text.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "SeqList.h" //业务结点 typedef struct _Teacher { char name[32]; int age; }Teacher; int main() { int ret = 0; Teacher t1, t2, t3; t1.age = 31; t2.age = 32; t3.age = 33; //1创建空的线性表的顺序存储结构 SeqList *list = NULL; list = SeqList_Create(10); if (NULL == list) { ret = -1; printf("func err SeqList_Create():%d\n",ret); return ret; } //2 插入元素 线性表的插入 采用头插法 ret = SeqList_Insert(list,(SeqListNode *)&t1,0); if (ret!=0) { ret = -2; printf("func err SeqList_Insert():%d\n", ret); return ret; } ret = SeqList_Insert(list, (SeqListNode *)&t2, 0); ret = SeqList_Insert(list, (SeqListNode *)&t3, 0); //3 遍历线性表 for (int i = 0; i < SeqList_Length(list); i++) { Teacher *tmp = (Teacher *)SeqList_Get(list,i);//获取链表结点的位置 if (NULL == tmp) { ret = -3; printf("func err SeqList_Get():%d\n", ret); return ret; } printf("age:%d\t",tmp->age); } //4 删除线性表结点 while (SeqList_Length(list) > 0) { Teacher *tmp = (Teacher *)SeqList_Delete(list,0); if (NULL == tmp) { ret = -4; printf("func err SeqList_Delete():%d\n", ret); return ret; } printf("age:%d\t", tmp->age); } //5 销毁线性表 SeqList_Destroy(list); system("pause"); return 0; }
线性表的顺序存储结构,在存,读数据时,不管是哪个位置,时间复杂度都是O(1),而插入或删除元素时候,时间复杂度是O(n)。这就说明比较适合元素个数不太变化,而更多是存取元素的应用.
线性表顺序存储结构的优缺点
长处:1、无须为表示表中元素之间的逻辑关系而添加额外的存储空间。
2、能够高速的存取表中任一位置的元素。
缺点:1、插入和删除操作须要移动大量的元素。
2、当线性表长度变化较大时,难以确定存储空间的容量。
3、造成存储空间的“碎片”。
========================================
但是有一点须要注意,能够高速的存取表中任一位置的“存”,和“插入”有什么差别呢?
“存”的意思表达的就是给线性表的任何位置赋值,表达为程序代码为 arr[3] = 100;
"插入"的意思表达的是在第i个位置插入一个元素。
比方插入线性表的第三个位置,就是第三个元素后的每一个元素都要向后移动一位(数组的长度假定够长)。
for(int i=3;i<10;i++){
arr[i+i] = arr[i];
}
这就说明线性顺序存储结构比較适合元素个数不太变化。而很多其它的是存取数据的应用。
线性表的顺序存储结构理解:
实现底层算法与业务结点的分离,采用的是插入的结点,像二维数组的行元素,每个行元素指向一个Teacher的结构体,故你插入多少条信息都是可以的
//线性表顺序存储设计与实现测试框架 //SeqList.h #ifndef _SEQLIST_H_ #define _SEQLIST_H_ typedef void SeqList; typedef void SeqListNode; //这两句话意思: //C语言里面的typedef, 字面上理解就是类型的定义, 也就是给内置的或自定义的数据类型重新命名 //SeqList* SeqList_Create(int capacity); //这样一看返回值就知道是返回值是链表 //void * SeqList_Create(int capacity); //如果这样,使用者一看只知道是返回指针,不知道具体的,可读性很差 //所以才会给void起别名,封装好的底层函数,提供给使用者使用,使用者会给容易懂 //创建并且返回一个空的线性表 SeqList* SeqList_Create(int capacity); //销毁一个线性表list void SeqList_Destroy(SeqList* list); //将一个线性表list中的所有元素清空, 线性表回到创建时的初始状态 void SeqList_Clear(SeqList* list); //返回一个线性表list中的所有元素个数 int SeqList_Length(SeqList* list); //返回一个线性表list中的容量 int SeqList_Capacity(SeqList* list); //向一个线性表list的pos位置处插入新元素node int SeqList_Insert(SeqList* list, SeqListNode* node, int pos); //获取一个线性表list的pos位置处的元素 SeqListNode* SeqList_Get(SeqList* list, int pos); //删除一个线性表list的pos位置处的元素 返回值为被删除的元素,NULL表示删除失败 SeqListNode* SeqList_Delete(SeqList* list, int pos); #endif
//SeqList.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "SeqList.h" //在结构体中套一级指针 typedef struct _tag_SeqList { int length;//线性表的长度 int capacity;//数组的长度-存放线性表的存储空间的长度 unsigned int *node;//链表需要有内存空间存储装元素-根据容量来分配内存空间-需要动态分配内存空间 int node[] }TSeqList; //创建并且返回一个空的线性表 SeqList* SeqList_Create(int capacity) { int ret = 0; if (capacity <= 0) { ret = -1; printf("func err (capacity <= 0):%d\t", ret); return NULL; } //1 线性表申请动态内存空间 TSeqList *tmp = (TSeqList *)malloc(sizeof(TSeqList));//开辟一片内存空间,大小是TSeqList类这么大 if (NULL == tmp) { ret = -2; printf("func err malloc:%d\t", ret); return NULL; } //开辟的内存,完成初始化 memset(tmp,0,sizeof(TSeqList)); //2 根据容量分配内存大小 tmp->node = (unsigned int *)malloc(sizeof(unsigned int)*capacity);//创建node结点的内存空间大小-相当于二维数组的行元素个数 if (NULL == tmp->node) { ret = -3; printf("func err malloc:%d\t", ret); return NULL; } tmp->capacity = capacity; tmp->length = 0; return tmp; } //销毁一个线性表list void SeqList_Destroy(SeqList* list) { int ret = 0; if (NULL == list) { ret = -1; printf("func err (NULL == list):%d\t", ret); } //1 缓存下来 进行操作 TSeqList *tmp = NULL; tmp = (TSeqList *)list; //2 先申请 后释放 if (tmp->node != NULL) { free(tmp->node); } if (tmp!=NULL) { free(tmp); } } //将一个线性表list中的所有元素清空, 线性表回到创建时的初始状态 void SeqList_Clear(SeqList* list) { int ret = 0; if (NULL == list) { ret = -1; printf("func err (NULL == list):%d\t", ret); } //1 缓存下来 进行操作 TSeqList *tmp = NULL; tmp = (TSeqList *)list; //2 线性表中的长度置空 tmp->length = 0; //3 重新将线性表中创建的结点初始化 memset(list,0,tmp->capacity * sizeof(unsigned int)); // 会把所有的置空 } //返回一个线性表list中的所有元素个数 int SeqList_Length(SeqList* list) { int ret = 0; if (NULL == list) { ret = -1; printf("func err (NULL == list):%d\t", ret); return ret; } //1 缓存下来 进行操作 TSeqList *tmp = NULL; tmp = (TSeqList *)list; return tmp->length; } //返回一个线性表list中的容量 int SeqList_Capacity(SeqList* list) { int ret = 0; if (NULL == list) { ret = -1; printf("func err (NULL == list):%d\t", ret); return ret; } //1 缓存下来 进行操作 TSeqList *tmp = NULL; tmp = (TSeqList *)list; return tmp->capacity; } //向一个线性表list的pos位置处插入新元素node int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) { int ret = 0; if (NULL == list || NULL == node||pos < 0) { ret = -1; printf("func err (NULL == list || NULL == node||pos < 0):%d\t", ret); return ret; } //1 缓存下来 进行操作 TSeqList *tmp = NULL; tmp = (TSeqList *)list; //注意1:线性表长度应该小于等于数组的长度 if (tmp->length >=tmp->capacity) { ret = -2; printf("func err (tmp->length >=tmp->capacity):%d\t", ret); return ret; } //注意2:容错修正 假设容量为20,此时线性表长度为6,pos却为10,这个时候可以做容错修正,直接修正为尾插法 if (pos >tmp->length) { pos = tmp->length; } //2 元素后移 int i; for ( i = tmp->length; i > pos; i--) { tmp->node[i] = tmp->node[i - 1];//后移 //t[pos+1] = t[pos+1-1]=t[pos] } //3 空出的位置插入新结点 tmp->node[i] = (unsigned int )node;//这里装二维数组的行的一个元素,这个行元素指向业务结点teacher这个结构体,所以teacher里面装多少信息,都是可以的 //4 线性表长度+1 tmp->length++; return ret; } //获取一个线性表list的pos位置处的元素 SeqListNode* SeqList_Get(SeqList* list, int pos) { int ret = 0; if (NULL == list || pos < 0) { ret = -1; printf("func err (NULL == list || pos < 0):%d\t", ret); return NULL; } //1 缓存下来 进行操作 TSeqList *tmp = NULL; tmp = (TSeqList *)list; //获取一个线性表list的pos位置处的元素 tmp = (SeqListNode *)tmp->node[pos]; return tmp; } //删除一个线性表list的pos位置处的元素 返回值为被删除的元素,NULL表示删除失败 SeqListNode* SeqList_Delete(SeqList* list, int pos) { int ret = 0; if (NULL == list || pos < 0) { ret = -1; printf("func err (NULL == list || pos < 0):%d\t", ret); return NULL; } //1 缓存下来 进行操作 TSeqList *tmp = NULL; tmp = (TSeqList *)list; //2 缓存删除元素 TSeqList *Deletemp = NULL; Deletemp = (SeqListNode *)tmp->node[pos]; //3 前移 for (int i = pos+1; i < tmp->length; i++) { tmp->node[i-1] = tmp->node[i]; } //4 删除元素后 线性表长度减1 tmp->length--; return Deletemp; }
//线性表顺序存储设计与实现测试框架 //text.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "SeqList.h" //业务结点 typedef struct _Tag_Teacher { int name; int age; int age1; double aa; double bb; double cc; double dd; double ee; }Teacher; int main() { int ret = 0; Teacher t1, t2, t3; t1.age = 11; t1.name = 11; t1.age1 = 11; t1.aa = 11; t1.bb = 11; t1.cc = 11; t1.dd = 11; t1.ee = 11; //t2.age = 12; //t2.name = "shao12"; //t2.aa = 11; //t3.age = 13; //t3.name = "shao13"; //t3.aa = 11; //1 创建空的线性表的顺序存储结构 SeqList *list = NULL; list = SeqList_Create(1); if (NULL == list) { ret = -1; printf("func err SeqList_Create():%d\n", ret); return ret; } //2 插入元素 线性表的插入 采用头插法 ret = SeqList_Insert(list,(SeqListNode *)&t1,0); if (ret!=0) { ret = -2; printf("func err SeqList_Insert():%d\n",ret); return ret; } //清除链表 //SeqList_Clear(list); ret = SeqList_Capacity(list); printf("func SeqList_Capacity():%d\n", ret); ret = SeqList_Insert(list, (SeqListNode *)&t1, 0); ret = SeqList_Insert(list, (SeqListNode *)&t2, 0); ret = SeqList_Insert(list, (SeqListNode *)&t3, 0); //3 遍历线性表 for (int i = 0; i < SeqList_Length(list);i++) { Teacher *temp = (Teacher *)SeqList_Get(list,i); if (NULL == temp) { ret = -3; printf("func err SeqList_Get():%d\n", ret); return ret; } //printf("Teacher age:%d\t",temp->age); printf("年龄:%d,name:%d,naa:%f", temp->age,temp->name,temp->ee); } //4 删除线性表结点 while (SeqList_Length(list) > 0) { Teacher *temp = (Teacher *)SeqList_Delete(list,0); if (NULL == temp) { ret = -4; printf("func err SeqList_Delete():%d\n", ret); return ret; } //printf("Teacher age:%d\t", temp->age); printf("年龄:%d,name:%d,naa:%f", temp->age, temp->name, temp->ee); } //5 销毁链表 SeqList_Destroy(list); printf("Teacher age:%d\t", sizeof(unsigned int));//sizeof(unsigned int) 4 32 printf("Teacher age:%d\t", sizeof(unsigned int*));//指针在32位编译器中是4个字节,在64位是8个字节 system("pause"); return ret; }