顺序表实现—数据结构
创始人
2024-01-17 08:25:06
0

文章目录

  • 一、顺序表概念及结构
  • 二、动态顺序表和静态顺序表的选择
  • 三、动态顺序表的实现逻辑
    • (1)创建结构体
    • (2)具体函数实现
      • (*)顺序表初始化
      • (*)释放顺序表
      • (*)打印顺序表
      • (*)是否需要扩容
      • (*)顺序表尾插
      • (*) 顺序表头插
      • (*)顺序表尾插删除
      • (*)顺序表头插删除
      • (*)顺序表查找
      • (*)顺序表在pos位置插入x
      • (*)顺序表删除pos位置的值
  • 四、动态顺序表实现代码
    • (1)test.c
    • (2)SeqList.h
    • (3)SeqList.c
  • 五、动态顺序表测试结果

一、顺序表概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删。一般分为静态顺序表和动态顺序表。

二、动态顺序表和静态顺序表的选择

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以我们实现动态顺序表。

三、动态顺序表的实现逻辑

(1)创建结构体

typedef int SLDateType;
typedef struct SeqList
{SLDateType* a;int size;int capacity; 
}SL;

使用动态顺序表先创建结构体是必须的,先使用typedef int SLDateType;是为了方便改类型,在结构体里创建三个成员变量,SLDateType* a,为了方便增容,用指针的形式,int size代表a指向空间里的个数,int capacity代表a指向空间里的容量。

(2)具体函数实现

(*)顺序表初始化

void SeqListInit(SL* ps)
{assert(ps);ps->a = NULL;ps->size = 0;ps->capacity = 0;}

先用assert断言,为了更方便查看在哪个地方出错,初始化就是把ps指向的结构体成员变量a置为空指针,size和capacity置为0。

(*)释放顺序表

void SeqListDestroy(SL* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->size = 0;ps->capacity = 0;
}

释放顺序表也就是把a指向的空间的释放掉,并把a置为空指针,而另外两个成员变量置为0。

(*)打印顺序表

void SeqListPrint(SL* ps)
{assert(ps);for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}

打印顺序表只需要用for循环依次打印,用ps找到size,即成员个数,再用printf进行打印,ps找到数组a。

(*)是否需要扩容

void if_add(SL*ps)
{if (ps->capacity == ps->size){int NewCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDateType* tmp = (SLDateType*)realloc(ps->a, NewCapacity*sizeof(SLDateType));if (tmp == NULL){perror("realloc fail");exit(-1);}ps->a = tmp;ps->capacity = NewCapacity;}
}

为了提高代码的可读性,把是否需要扩容封装一个函数,而且下面有好多函数需要用到。
先判断capacity和size是否相等,如果相等,说明需要增容,再用三目运算符判断capacity是否等于0,如是则设置一个有一定大小的初始值,反之,则指定的倍数进行扩容。再把它赋给Newcapacity,再realloc进行开辟空间,用另外一个指针tmp表示,再判断tmp是否为空,如是则用perror显示开辟失败,并非正常退出程序exit(-1),反之则把新指针再赋给原来的a,最后capacity进行更新,Newcapacity赋给capacity。

(*)顺序表尾插

void SeqListPushBack(SL* ps, SLDateType x)
{assert(ps);if_add(ps);ps->a[ps->size] = x;ps->size++;
}

尾插先判断空间是否足够,再把x依次插入ps->size元素下标的位置,并进行ps->size加加,记录已尾插的个数。

(*) 顺序表头插

void SeqListPushFront(SL* ps, SLDateType x)
{assert(ps);if_add(ps);for (int i = ps->size - 1; i >=0; i--){ps->a[i + 1] = ps->a[i];}ps->a[0] = x;ps->size++;
}

头插也是先判断空间是否足够,再从后面进行尾插,用for循环从i=ps->size开始,每头插一个就把此位置的值往后移,直到第一个位置也就是0位置可用的时候,在把x赋给0位置处,直到i<0为止,最后size加加。

(*)顺序表尾插删除

void SeqListPopBack(SL* ps)
{assert(ps->size > 0);ps->size--;
}

头删,需要用asser断言一下,里面的内容为ps->size>0,防止size<0,以便告诉我们在哪出错,最后直接ps->szie–

(*)顺序表头插删除

void SeqListPopFront(SL* ps)
{assert(ps);for (int i = 1; i < ps->size; i++){ps->a[i-1] = ps->a[i];}ps->size--;
}

头插删除,直接用for循环把后面内容往前移,注意i是从1开始的,如果写成0会越界,而且也只能从1开始,因为删除的是开头的元素,最后ps->szie–。

(*)顺序表查找

int SeqListFind(SL* ps, SLDateType x)
{for (int i = 0; i < ps->size; i++){if (ps->a[i] == x){return i;}}return -1;
}

顺序表查找返回值是int类型,返回的是下表元素,那就用for循环直接遍历,如果找到x,就返回下标元素i,最后遍历完也没有找到返回-1。
这个函数需要结合测试函数test.c的部分代码用,如下,如果返回不是-1,就打印下标元素i,否则打印失败。

int ret = SeqListFind(&sl, 6);if (ret!=-1){printf("%d\n", ret);}else{printf("find fail\n");}

(*)顺序表在pos位置插入x

void SeqListInsert(SL* ps, int pos, SLDateType x)
{assert(ps);assert(pos <= ps->size);if_add(ps);for (int i = ps->size-1; i >= pos; i--){ps->a[i + 1] = ps->a[i];}ps->a[pos] = x;ps->size++;
}

顺序表在下标元素pos插入x,先写两个断言函数,pos不能比szie大,因为我们是在size个数里面插入,再判断是否需要扩容,再用for循环进行移动元素,初始位置为当前数组的最后一个元素开始,直到pos结束,也就是pos位置可用可插入的时候再进行插入x,最后size++。

(*)顺序表删除pos位置的值

void SeqListErase(SL* ps, int pos)
{assert(ps && pos < ps->size);for (int i = pos; i < ps->size-1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}

顺序表删除下标pos位置的值,同上用assert进行断言,从
pos位置开始,进行覆盖,直到ps->size-1结束,防止越界,因为有可能capacity等于size,最后size–。

四、动态顺序表实现代码

(1)test.c

#include"SeqList.h"int main()
{SL sl;SeqListInit(&sl);SeqListPushBack(&sl, 1);SeqListPushBack(&sl, 2);SeqListPushBack(&sl, 3);SeqListPushBack(&sl, 4);SeqListPrint(&sl);SeqListPopBack(&sl);SeqListPopBack(&sl);SeqListPopBack(&sl);SeqListPrint(&sl);SeqListPushFront(&sl,3);SeqListPushFront(&sl, 4);SeqListPushFront(&sl, 5);SeqListPrint(&sl);SeqListPopFront(&sl);SeqListPopFront(&sl);SeqListPrint(&sl);int ret = SeqListFind(&sl, 6);if (ret!=-1){printf("%d\n", ret);}else{printf("find fail\n");}SeqListInsert(&sl, 1, 4);SeqListPrint(&sl);SeqListInsert(&sl, 3, 6);SeqListPrint(&sl);SeqListErase(&sl, 2);SeqListPrint(&sl);SeqListDestroy(&sl);return 0;
}

(2)SeqList.h

#pragma once//防止头文件包含
#include 
#include 
#include typedef int SLDateType;
typedef struct SeqList
{SLDateType* a;int size;int capacity; 
}SL;
void SeqListInit(SL* ps);//顺序表初始化
void SeqListDestroy(SL* ps);//释放顺序表void SeqListPrint(SL* ps);//打印顺序表
void SeqListPushBack(SL* ps, SLDateType x);//顺序表尾插
void SeqListPushFront(SL* ps, SLDateType x); //顺序表头插
void SeqListPopFront(SL* ps);//顺序表头插删除
void SeqListPopBack(SL* ps);//顺序表尾插删除
void if_add(SL* ps);//是否需要扩容int SeqListFind(SL* ps, SLDateType x);//顺序表查找
void SeqListInsert(SL* ps, int pos, SLDateType x); 顺序表在pos位置插入x
void SeqListErase(SL* ps, int pos);// 顺序表删除pos位置的值

(3)SeqList.c

#include"SeqList.h"
void SeqListInit(SL* ps)
{assert(ps);ps->a = NULL;ps->size = 0;ps->capacity = 0;}
void SeqListDestroy(SL* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->size = 0;ps->capacity = 0;
}
void SeqListPrint(SL* ps)
{assert(ps);for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}
void if_add(SL*ps)
{if (ps->capacity == ps->size){int NewCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDateType* tmp = (SLDateType*)realloc(ps->a, NewCapacity*sizeof(SLDateType));if (tmp == NULL){perror("realloc fail");exit(-1);}ps->a = tmp;ps->capacity = NewCapacity;}
}
void SeqListPushBack(SL* ps, SLDateType x)
{assert(ps);if_add(ps);ps->a[ps->size] = x;ps->size++;
}
void SeqListPopBack(SL* ps)
{assert(ps->size > 0);ps->size--;
}
void SeqListPushFront(SL* ps, SLDateType x)
{assert(ps);if_add(ps);for (int i = ps->size - 1; i >=0; i--){ps->a[i + 1] = ps->a[i];}ps->a[0] = x;ps->size++;
}
void SeqListPopFront(SL* ps)
{assert(ps);for (int i = 1; i < ps->size; i++){ps->a[i-1] = ps->a[i];}ps->size--;
}
int SeqListFind(SL* ps, SLDateType x)
{for (int i = 0; i < ps->size; i++){if (ps->a[i] == x){return i;}}return -1;
}void SeqListInsert(SL* ps, int pos, SLDateType x)
{assert(ps);assert(pos <= ps->size);if_add(ps);for (int i = ps->size-1; i >= pos; i--){ps->a[i + 1] = ps->a[i];}ps->a[pos] = x;ps->size++;
}
void SeqListErase(SL* ps, int pos)
{assert(ps && pos < ps->size);for (int i = pos; i < ps->size-1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}

五、动态顺序表测试结果

在这里插入图片描述

上一篇:点嘴唇,踢秋千

下一篇:卷耳朵

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...