《详解顺序表》
目录:
一、顺序表的定义及其特点
顺序表又称顺序存储结构,是线性表的一种,专门存储逻辑关系为“一对一”的数据。顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。二、顺序表的运算(概述)
1.初始化
顺序表的初始化时除了要申请足够大小的物理空间之外,为了方便后续的数据处理,应当还有实时记录下顺序表申请的存储容量与顺序表的长度即数据元素个数。
2.查找
顺序表的查找运算是查找表中元素$a_ i$ 的值。顺序表具有随机存取的特点,因此数据元素$a_i$的值可以直接通过数组下标定位取得。
3.插入
顺序表的插入运算是在顺序表L的元素$a_i$之后插入新的元素x。若i = -1,则表示将新的元素插入顺序表的最前面。首先需要对i是否越界、顺序表存储空间是否已满进行判断。新元素x插入到顺序表之前,需要将下标之后的所有元素依次向后移动一个位置。
4.删除
顺序表的删除运算的功能是将元素$a_i$删除。须先对i是否越界、顺序表是否为空进行判断。在顺序表中,逻辑上相邻的数据元素在物理位置上也需相邻,因此不能直接简单删除元素$a_i$,而需将下标之后的所有元素依次向前移动一个位置。
5.输出
顺序表的输出运算是将顺序表的元素依次输出。
三、顺序表的实现
四、完整的Demo
函数与结构体声明(SequenceList.h):
/* SequenceLsist.h 顺序表 */ #define MAXSIZE 598//顺序表最大长度 typedef int ListType;//顺序表存储的数据类型,在此定义别名以方便变更存储类型 typedef struct SequenceList{ ListType data[MAXSIZE];//定义用于存储的数组及其长度 int length;//当前顺序表数据下标 }SeqList; /* 函数声明 */ int init(SeqList *L);//初始化顺序表 int getSize(SeqList *L);//获取当前存储的数据长度 int isEmpty(SeqList *L);//顺序表判空 int isFull(SeqList *L);//顺序表判满 int insert(SeqList *L, int site, ListType data); //顺序表插入,site为位置,data为需要插入的数据 int update(SeqList *L, int site, ListType data);//变更顺序表元素 int expurgate(SeqList *L, int site);//移除site上的数据 int check(SeqList *L, int site, int state);//操作位置合法性判断(state为1时为插入操作) ListType get(SeqList *L, int site);//获取第site上的数据 int find(SeqList *L, ListType data);//查找顺序表中是否存在该元素 void clear(SeqList *L); //清空顺序表 void print(SeqList *L);//打印顺序表
函数的实现(SequenceList.c):
#include "SequenceList.h" #include <stdio.h> int init(SeqList *L) { L->length = -1; return 0; } int getSize(SeqList *L) { return (L->length + 1); } int isEmpty(SeqList *L) { // printf("L->length + 1:%d",L->data[0]); return (L->length + 1) == 0 ? 1 : 0; } int isFull(SeqList *L) { return (L->length + 1) == MAXSIZE ? 1 : 0; } int check(SeqList *L, int site, int state) { int flag = 0; if(state){//判断是否是插入操作 if(site > 0 && site < MAXSIZE){ flag = 1; } } else {//(删除 || 读取 || 更新)位置合法判断 if (site > 0 && site <= (L->length + 1)){ flag = 1; } } return flag; } int insert(SeqList *L, int site, ListType data) { if(!isFull(L)){//判断是否已满 if(check(L, site, 1)){//合法性判断 for(int i = (L->length);i > (site - 1);i--){//将插入位置之后的元素向后移 L->data[i + 1] = L->data[i]; } L->data[site - 1] = data;//插入元素 L->length++; return 1; } else { printf("插入位置不合法!\n\n"); return 0; } } else { printf("顺序表已满!\n\n"); return 0; } } int expurgate(SeqList *L, int site) { if(!isEmpty(L)){//判断是否为空 if(check(L, site, 0)){//合法性判断 for(int i = (site - 1);i <= (L->length);i++){ L->data[i - 1] = L->data[i]; } L->length--; return 1; } else { printf("删除位置不合法!\n\n"); return 0; } } else { printf("顺序表为空!\n\n"); return 0; } } void clear(SeqList *L) { L->length = -1; } ListType get(SeqList *L, int site) { if(!isEmpty(L)){ if(check(L, site, 0)){ return L->data[site - 1]; } else{ printf("读取位置不合法!\n\n"); } } else { printf("顺序表为空!\n\n"); } return 0; } void print(SeqList *L){ if(isEmpty(L)){ printf("顺序表为空!\n\n"); return ; } else { printf("当前顺序表为: ["); for(int i = 0;i <= L->length;i++){ printf("%d", L->data[i]); if(i == L->length){ printf("]\n\n"); } else{ printf(", "); } } } } int find(SeqList *L, ListType data){ int flag = 0; for(int i = 0;i <= L->length;i++){ if(data == L->data[i]){ flag = 1; printf("元素存在,为顺序表中第%d个元素\n", (i + 1)); } } return flag; } int update(SeqList *L, int site, ListType data) { int flag = 0; if(isEmpty(L)){//判空 printf("顺序表为空!\n\n"); } else { if(check(L, site, 0)){ L->data[site - 1] = data; flag = 1; } else { printf("更新位置不合法!\n\n"); } } return flag; }
主函数(main.c):
#include <stdio.h> #include <stdlib.h> #include "SequenceList.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main() { SeqList L; int operate; int site; int data; printf("\n\n\n"); do{ printf("<----------------------------------------------------顺序表演示程序--------------------------------------------------->\n"); printf("0. 退出程序\n"); printf("1. 初始化顺序表\n"); printf("2. 打印顺序表\n"); printf("3. 插入元素\n"); printf("4. 删除元素\n"); printf("5. 查找元素\n"); printf("6. 变更元素\n"); printf("7. 获取元素\n"); printf("8. 顺序表判空\n"); printf("9. 顺序表判满\n"); printf("10. 顺序表长度查询\n"); printf("11. 清空顺序表\n"); printf("12. 帮助\n"); printf("请输入操作选项(0~11,0为退出):"); scanf("%d", &operate); // getchar(); switch (operate) { case 1: if(!init(&L)){ printf("初始化完成\n\n"); } else { printf("初始化失败\n\n"); } break; case 2: print(&L); break; case 3: printf("请输入插入位置与插入数据(以逗号间隔):"); scanf("%d,%d", &site,&data); insert(&L, site, data); break; case 4: printf("请输入删除位置:"); scanf("%d", &site); expurgate(&L, site); break; case 5: printf("请输入查找元素:"); scanf("%d", &data); if(!find(&L, data)) { printf("顺序表为空\n\n"); } break; case 6: printf("请输入更新位置与更新元素(以逗号间隔):"); scanf("%d,%d", &site, &data); update(&L, site, data); break; case 7: printf("请输入需要获取的位置:"); scanf("%d", &site); get(&L, site); break; case 8: if(isEmpty(&L)){ printf("顺序表为空\n\n"); } else { printf("顺序表不为空\n\n"); } break; case 9: if(isFull(&L)){ printf("顺序表已满\n\n"); } else { printf("顺序表未满\n\n"); } break; case 10: printf("该位置的元素为:%d", getSize(&L)); break; case 11: clear(&L); break; case 12: printf("本应用程序为数据结构-顺序表演示程序,用于课程实践与研究。由季文天老师指导,史恒珲开发。\n\n"); break; case 0: return 0; break; } } while(operate != 0); return 0; }
五、小结
发布博客还是一次,此次通过撰写博客也算重新梳理了一下数据结构的部分知识,对于顺序表的定义与操作算是切实掌握了。总的来说这种自己写下的文字的方式,确实是比过去看他人博客、文档等方式汲取的知识更为深刻。今后的应该多试着去自己描述、记录些什么。写下这篇博客是23.10.06的晚上,国庆假期的最后一天。代码在假期前已经完成九成,但因手头上的工作和调整状态,一直拖到收假才完成博客。也不单是写作业吧,也写给过去、当下、未来的自己:别忘了来时的路和说过的话,调整好状态做自己。
六、参考文献
王海艳等.《数据结构(C语言)》第二版[M].北京:人民邮电出版社,2020:10~14.