顺序表是数据结构中最简单的一种内存管理方式,可以将程序员想要存储的数据线性的进行存储,其中因为存储的数据在内存中是连续的,所以叫做顺序表。接下来看看动态顺序表是如何实现的。
一.在sequence.h头文件中进行函数的申明
二.在sequence.c源文件中进行函数的实现
三.在test.c源文件中进行代码测试
1.动态顺序表的创建
1. #pragma once 2. #define _CRT_SECURE_NO_WARNINGS 1 3. #include<stdio.h> 4. #include<stdlib.h> 5. typedef int type; 6. typedef struct sequence 7. { 8. type* p;//顺序表头地址 9. int sz;//顺序表有效数据个数 10. int capcity;//顺序表容量 11. }seq;
在sequence.h中创建一个结构体来对动态顺序表进行打包,其中内部需要声明是 顺序表的头地址,顺序表的属性(有效数据个数和容量)。
接下来,我们来实现顺序表的初始化
2.顺序表的初始化
顺序表的初始化无非就是为顺序表申请空间,初始化顺序表属性。
1. void intiseq(seq* psl) 2. { 3. //为顺序表申请空间 4. psl->p = (type*)malloc(sizeof(type) * 5);//在堆上申请五个type类型数据的空间 5. //初始化属性 6. psl->sz = 0;//初始化顺序表的有效数据 7. psl->capcity = 5;//给定容量 8. }
初始化后,顺序表才可以说具备了存储数据的能力。我们就可以对顺序表进行一系列的操作了,因为顺序表是在堆上申请的空间,所以在增删查改过后就得手动释放顺序表的空间,销毁顺序表,下面顺便实现一下对顺序表的销毁。
3.顺序表的销毁
顺序表的销毁无非就是释放一下顺序表的空间,置空一下属性。
1. void destroyseq(seq* psl) 2. { 3. free(psl->p);//释放顺序表内存空间 4. psl->p = NULL;//置空指针p,防止变为野指针 5. //置空属性 6. psl->sz = 0; 7. psl->capcity = 0; 8. }
在上面基本的操作过后,我们就可以正式的玩转顺序表了。
顺序表增加元素分为三种:尾部插入,头部插入,中间位置插入。在插入元素之前,我们需要对顺序表的容量和有效数据进行检查,防止顺序表满了,如果顺序表满了还需要进行扩容。写一个检查函数来实现。
4.顺序表容量检查
顺序表容量检查要实现的功能是判断内存空间是否已满,并实现扩容二倍的操作,这在顺序表插入元素时是至关重要的操作。
1. void checkseq(seq* psl) 2. { 3. if (psl->capcity == psl->sz)//如果容量等于有效数据个数,则内存不够,扩容 4. { 5. type* tmp =NULL; 6. tmp = realloc(psl->p, 2 * psl->capcity * sizeof(type)); 7. psl->p = tmp; 8. psl->capcity *= 2; 9. } 10. }
5.顺序表尾插
在顺序表尾部插入数据的操作只需要先插入,再增加有效数据个数
1. void pushbackseq(seq* psl, int n) 2. { 3. checkseq(psl);//检查容量 4. psl->p[psl->sz] = n;//在下标为sz处插入n 5. psl->sz++;//有效数据个数增加 6. }
6.顺序表头插
在顺序表头部插入数据只需要先挪动数据,再在头部插入数据,然后有效数据增加,具体步骤如下
1. void pushheadseq(seq* psl, int n) 2. { 3. checkseq(psl);//检查容量 4. //挪动 5. for (int i=psl->sz;i>=1;i--) 6. { 7. psl->p[i] = psl->p[i - 1]; 8. } 9. //插入 10. psl->p[0] = n; 11. //有效数据增加 12. psl->sz++; 13. }
7.顺序表中间位置插入
在顺序表中间位置的插入,需要先挪动此位置下标后面的数据,再在此下标插入数据,再有效数据增1
1. void pushmidseq(seq* psl, int pos,int n) 2. { 3. checkseq(psl);//检查容量 4. for (int i = psl->sz; i >=pos+1 ; i--) 5. { 6. psl->p[i] = psl->p[i - 1];//挪动数据 7. } 8. psl->p[pos] = n;//在pos下标处插入数据 9. psl->sz++;//有效数据加1 10. }
顺序表的插入元素到这里就算结束了,接下来我们玩转顺序表删除元素。
8.顺序表尾删
1. void popbackseq(seq* psl) 2. { 3. assert(psl->sz > 0);//断言 4. psl->sz--;//有效数据减一 5. }
首先,在顺序表尾部删除元素,只需要将有效数据个数减少1,就无法访问到尾部这个元素了,但是删除不可以无止境删除,当顺序表有效数据为0时,就不可以继续删除了,所以我们加一个断言。
9.顺序表头删
顺序表头删除只需要将头部数据覆盖,再将有效数据减一,具体步骤如下
1. void popheadseq(seq* psl)//头删 2. { 3. assert(psl->sz > 0); 4. for (int i = 1; i <psl->sz ; i++) 5. { 6. psl->p[i - 1] = psl->p[i];//覆盖头部元素 7. } 8. psl->sz--;//有效数据减一 9. }
10.顺序表中间位置删除
顺序表中间位置删除元素也是需要先将要删除位置的下标后面的元素整体向前覆盖,再有效数据减一。
1. void popmidseq(seq* psl,int pos)//中间删 2. { 3. assert(psl->sz > 0); 4. for (int i = pos; i < psl->sz-1; i++) 5. { 6. psl->p[i] = psl->p[i + 1];//要删除位置的下标后面的元素整体向前覆盖 7. } 8. psl->sz--;//有效数据个数减一 9. }
到这里,顺序表的插入删除已经结束了,下面介绍顺序表的查找和修改
11.顺序表元素查找
顺序表的元素查找就是返回要查找元素的下标,直接遍历或者二分即可,如果找不到,返回-1。
1. int searchseq(seq* psl, type n) 2. { 3. for (int i = 0; i < psl->sz; i++) 4. { 5. if (psl->p[i] == n) 6. return i; 7. } 8. return -1; 9. }
12.顺序表元素修改
顺序表的元素修改就更加简单了,只需要给出要修改元素的下标,再直接修改对应元素即可。
1. void modifyseq(seq* psl, int pos, type n) 2. { 3. psl->p[pos] = n; 4. }
顺序表玩转完了,下期我们玩转链表哈哈