- 定义和特点都和静态类型的顺序表一样(详见上一篇文章),但是代码结构不太一样,初始化时不太一样,需要使用malloc或者是realloc申请内存,比起静态顺序表,动态的更加好调整顺序表的大小。
- 具体代码
🥐1. 结构代码
🥐2. 初始化顺序表typedef int SeqDataType; #define OK 1 #define ERROR 0 typedef struct SeqList { SeqDataType* a; int size; int capacity; }SeqList, SEQ;
🥐3. 检查是否要扩容void SeqListInit(SeqList* pq) { assert(pq); pq-> a = NULL; pq-> capacity = 0; pq-> size = 0; }
思路讲解:
👉判断顺序表空间是否满了,也就是判断是否需要增容就是要看pq->size == pq->capacity?增容:不增容。
👉用条件运算符来确定增容后的新空间的大小,如果是仍未存储数据的新链表,则先让链表的容量为4(这个数值可以随便设置);如果已经存储了数据,但容量不够了,我们就让链表的空间每次增加一倍,也就是变成原来的两倍(可能有人会疑惑,为什么是两倍,其实这个也是为了减少数据的浪费,变成2倍比较保守)。
👉在扩容时用realloc,当realloc的第一个参数为0时,其效果等同于malloc,用realloc可以完美实现最初开辟空间和增容的功能。
👉检查tmp是否为空,也就是检查是否成功开辟了新的空间,非空则把tmp赋值给pq->a,最后千万不要忘记更改capacity的值。
🥐4.顺序表尾插void SeqCheckCapacity(SeqList *pq) { assert(pq); if(pq->capacity == pq->size) { int newcapacity = (pq->capacity == 0 ? 4: pq->capacity * 2); SeqDataType *tmp = (SeqDataType *)realloc(pq->a,sizeof(SeqDataType)*newcapacity); if(tmp == NULL) { printf("ERROR\n"); return ERROR; } pq->a = tmp; pq->capacity = newcapacity; } }
这里就需要注意在尾插前检查容量,并且不要忘记pq->size++。
🥐 5.顺序表头插void SeqListPushBack(SeqList* pq, SeqDateType x) { assert(pq); //检查空间大小 SeqCheckCapacity(pq); pq->a[pq->size] = x; pq->size++; }
需要将顺序表整体往后移动,空出头部一个位置给插入
🥐6. 顺序表尾删void SeqListPushFront(SeqList* pq, SeqDataType x) { int i; assert(pq); SeqCheckCapacity(pq); for(i=pq->size-1;i>=0;i--) { pq->a[i+1] = pq->a[i]; } pq->a[0] = x; pq->size++; }
直接将记录数组有效个数的变量size减减即可,这样就访问不到了
❗没必要对要删除的这个元素进行置空等等,因为不影响【因为当后面如果尾插的话,就会直接覆盖原来的数据了~】
🥐7.顺序表头删void SeqListPopBack(SeqList* pq) { assert(pq); if(pq->size == 0) return; pq->size--; }
需要将顺序表整体前移数据,覆盖第一位数据即达到删除的目的
🥐8. 查找元素void SeqListPopFront(SeqList* pq) { assert(pq); int i; if(pq->size == 0) return; for(i = 0;i<pq->size-1;i++) { pq->a[i] = pq->a[i+1]; } pq->size--; }
遍历顺序表一一比较查找是否有我们想要的元素。- 没有,则返回
-1
- 有,则返回元素的
下标
(若有多个符合要查找的元素,则返回优先找到的元素的下标)
🥐9.修改元素int SeqListFind(SeqList*pq, SeqDataType x) { int i; assert(pq); for(i = 0;i<pq->size;i++) { if(x== pq->a[i]) { return i; } } return -1; }
直接访问想要修改的元素的下标进行修改
💥特别注意: 修改元素的下标要在顺序表有效个数的范围内,修改第pos个元素,下标是pos-1
🥐10.任意位置前插入元素void SeqListModify(SeqList*pq, int pos, SeqDataType x) { //pos的取值在1<=pos<=pq->size assert(pq); if(pos < 1 || pos>pq->size) return; pq->a[pos-1] = x; }
将从顺序表中要插入的位置开始,往后原有的元素整体往后移动,腾出空位来插入
💥特别注意: 插入的位置要在顺序表有效个数的范围内
🥐11.任意位置删除元素void SeqListInsert(SeqList*pq, int pos, SeqDataType x) { int i; assert(pq); if(pos < 1 || pos > pq->size+1) return; SeqCheckCapacity(pq); for (i = pos->size;i>=pos;i--) { pq->a[i] = pq->a[i-1]; } pq->a[pos- 1] = x; pq->size++; }
将从顺序表中要删除的元素开始,往后所有的元素整体往前移动,后面的元素覆盖要删除的位置的元素,以达到删除
的目的
💥特别注意: 删除的位置要在顺序表有效个数的范围内
🥐12.打印顺序表void SeqListDelete(SeqList*pq, int pos) { int i; assert(pq); if(pq->size == 0) return; if(pos < 1 || pos >pq->size) return; for (i = pos;i < pq->size;i++) { pq->a[i-1] = pq->a[i]; } pq->size--; }
遍历顺序表一一打印即可
🥐13.销毁顺序表void SeqListPrint(SeqList* pq) { int i; assert(pq); for(i = 0;i< pq->size;i++) { printf("%d ",pq->a[i]); } printf("\n"); }
直接将顺序表中的成员变量置为0
,且释放顺序表的空间即可void SeqListDestory(SeqList* pq) { assert(pq); free(pq->a); pq->a = NULL; pq->capacity = pq->size = 0; }
- 没有,则返回
数据结构之线性表的顺序存储结构(动态)
于 2023-03-03 10:11:53 首次发布