顺序表的简单原理实现

简介: 顺序表的简单原理实现

注意看看代码的注释!!!!!(干货)

主要是功能是增删改查这些;

源码:头文件中

#define  _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLDatatype;
int newcapacity = 0;
struct SeqList
{
  SLDatatype* data;//其实我们有了地址还可以搞链表,我们动态顺序表存储方式其实是顺序存储的,所以我们不需要去记节点
  int size;
  int capacity;
};
typedef struct SeqList SL;
void SLInti(SL* ps);//初始化,千万不要写成void SLInti(SL s),因为函数在传参的时候,形参是实参的一份临时拷贝
void SLInti(SL* ps)//一定得开辟个空间变量,因为他不像链表一样有个地址即可
{
  ps->data = NULL;
  ps->capacity = 0;
  ps->size = 0;
}
void CheckCapacity(SL* ps);//检查容量
void CheckCapacity(SL* ps)
{
  if (newcapacity == ps->capacity)
  {
    newcapacity = ps->capacity == 0 ? 4 : newcapacity * 2;//这个有什么作用呢,
     //因为这里是我们如果空间为0,扩两倍那等于没阔,所以我们如果是0的话空间就给4,而且用三目操作符又比
     //ifelse代码更简介,效率更高
    SLDatatype* ptr = (SLDatatype*)realloc(ps->data, newcapacity * sizeof(SLDatatype));
    if (ptr == NULL)
    {
      perror("realloc fail");
      exit(-1);
    }
    ps->data = ptr;//为什么要给指针赋值,因为当我们在申请空间时,操作系统会去识别你需要的的空间是否被占用,如果
    //被占用那么操作系统会去重新分配个地址,释放原来的空间,并把原先的数据拷贝到新地址指向的空间
    //,因为我SL * ps们不知道realloc扩容后返回的地址是异地扩容还是原地扩容
  }
}
void SListPushBack(SL* ps, SLDatatype X);//尾插
void SListPushBack(SL* ps, SLDatatype X)//尾插
{
  CheckCapacity(ps);
  ps->data[ps->size] = X;
  ++ps->capacity;
  ++ps->size;
}
void SListPushFont(SL* ps, SLDatatype X);//头插
void SListPushFont(SL* ps, SLDatatype X)//头插
{
  assert(ps->size >= 0);//只能在有效数据内插入
  CheckCapacity(ps);
  int i = 0;
  for (i=ps->size;i>=1;--i)//从最后一个数据开始依次往后覆盖,最后把首元素插入
  {
    assert(ps->size < newcapacity);
    ps->data[i] = ps->data[i - 1];
  }
  ps->data[0] = X;//首元素插入
  ++ps->size;
  ++ps->capacity;
}
void SListPopBack(SL* ps, SLDatatype X);//尾删
void SListPopBack(SL* ps,SLDatatype X)
{ 
  assert(ps->size > 0);
  --ps->size;//删除一个size减去一个
}
void SListPrint(SL* ps);//打印数据
void SListPrint(SL* ps)
{
  for (int i=0;i<=ps->size-1;i++)
  {
    printf("%d->", ps->data[i]);//我们只打印有效数据就行,因为我们的size和capacity
  }//一直在追踪整个顺序表,我添加一个size+1一次,capacity+1次
  printf("\n");
}
void SListPopFront(SL* ps);//头删
void SListPopFront(SL* ps)
{
  assert(ps->size > 0);//判断里面有木有数
  assert(ps->capacity > 0);//没有就不删除
  for (int i=1;i<ps->size;i++)//直接看作删完,后面覆盖到前面,从第二个开始依次往前覆盖
  {
    ps->data[i - 1] = ps->data[i];
  }
  --ps->size;//删完之后减去个数
  --ps->capacity;//删完之后减去占用空间
}
int SListSearch(SL* ps, SLDatatype X);//搜索你要的数——返回下标,没找到返回-1
int SListSearch(SL* ps, SLDatatype X)//这里的SLDatatype X是你要找的数
{
  assert(ps->capacity > 0);
  for (int i=0;i<ps->size;i++)
  {
    if (ps->data[i]==X)
    {
      return i;//找到想要的数,返回他的下标
    }
  }
  return -1;//没找到返回-1
}
void SListDesignInsert(SL* ps, SLDatatype X,int x);//指定插入——找到那个数我们才插入,否则就不插入,
//所以我们在这里会判断一个是否找到下标
void SListDesignInsert(SL* ps, SLDatatype X,int x)//这里的SLDatatype X是我们找到的下标
{
  assert(ps->capacity > 0);
  CheckCapacity(ps);
  for (int i=ps->size;i>X;i--)//从后面的数依次存到后面
  {
    ps->data[i] = ps->data[i - 1];//没问题
  }
  ps->data[X] = x;
  ++ps->size;
  ++ps->capacity;
}
void SListDesignErase(SL* ps, SLDatatype X);
void SListDesignErase(SL* ps, SLDatatype X)//指定删除
{
  assert(ps->capacity > 0);
  for (int i=0;i<ps->size;i++)
  {
    if (X == ps->data[i])
    {
      int j = 0;
      for (j = i;j < ps->size-1;j++)//从前面的顺序依次往前面放
      {
        ps->data[j] = ps->data[j+1];//没问题
      }
      --ps->size;
      --ps->capacity;
      break;
    }
  }
}
void SListInsert(SL* ps, SLDatatype X,int x);
void SListInsert(SL* ps,SLDatatype X,int x)//随机插入---(其实我们也可以变成头插)——此时的SLDatatype X是下标
{
  assert(ps);
  assert(X >= 0 && X<=ps->size);
  CheckCapacity(ps);
  int Src = X ;
  int End = ps->size;
  while (Src<End)//要把头插和尾插的方面也考虑进去
  {
    ps->data[End] = ps->data[End - 1];
    --End;
  }
  ps->data[X] = x;
  ++ps->size;
  ++ps->capacity;
}
void SListErase(SL* ps, SLDatatype X);//随机删除——此时的SLDatatype X是下标
void SListErase(SL* ps, SLDatatype X)
{
  assert(ps);
  assert(ps->size>0);
  assert(X >= 0 && X<=ps->size - 1);
  int Src = X;
  int End = ps->size - 1;
  while (Src<End)//删除的顺序跟插入的顺序是不一样的
  {
    ps->data[Src] = ps->data[Src + 1];
    Src++;
  }
  --ps->size;
  --ps->capacity;
}
void Dsetory(SL* ps);
void Dsetory(SL* ps)
{
  free(ps->data);
  ps->data = NULL;
  ps->capacity = 0;
  newcapacity = 0;
  ps->size = 0;
}

源码:源文件中

#define  _CRT_SECURE_NO_WARNINGS 1
#include "10.26.h"
#include <stdio.h>
int main()
{
  SL s1;
  SLInti(&s1);
  SListPushFont(&s1, 2);
  SListPushFont(&s1, 3);
  SListPushFont(&s1, 4);
  SListPushFont(&s1, 5);
  SListPushFont(&s1, 6);
  SListDesignInsert(&s1, SListSearch(&s1, 6),7);
  SListPushBack(&s1, 7);
  SListPushBack(&s1, 8);
  SListPushBack(&s1, 9);
  SListPushBack(&s1, 10);
  SListDesignInsert(&s1, SListSearch(&s1, 4), 7);
  SListDesignInsert(&s1, SListSearch(&s1, 6), 7);
  SListDesignErase(&s1, SListSearch(&s1, 6), 7);
  SListPrint(&s1);
  SListInsert(&s1, 2, 8);
  SListInsert(&s1, 0, 8);
  SListInsert(&s1, 13, 8);
  SListPrint(&s1);
  SListErase(&s1, 0);
  SListErase(&s1, 10);
  SListErase(&s1, 2);
  SListPrint(&s1);
  Dsetory(&s1);
}

分析1

这个有些基础弱的可能会被他搞混,其实我们的原理是这样的

并且我们的结构体内容也不会随着开辟SLDatatype*指向的空间而改变

并且里面有很多需要注意的点

1.

2.

3.

4.

5.

6.

每次记得断言一下,然后继续优化,继续测试慢慢完善

相关文章
|
6月前
|
消息中间件 JSON 自然语言处理
Python多进程日志以及分布式日志的实现方式
python日志模块logging支持多线程,但是在多进程下写入日志文件容易出现下面的问题: PermissionError: [WinError 32] 另一个程序正在使用此文件,进程无法访问。 也就是日志文件被占用的情况,原因是多个进程的文件handler对日志文件进行操作产生的。
|
6月前
|
存储 分布式计算 资源调度
|
6月前
|
Oracle 安全 关系型数据库
Oracle安装部署再也不用头疼了,分享一个实用的一键部署脚本,建议收藏!
Oracle安装部署再也不用头疼了,分享一个实用的一键部署脚本,建议收藏!
194 0
|
7月前
|
SQL Oracle 关系型数据库
|
9月前
|
存储 JavaScript 前端开发
vue实现一个账号在同一时间只有一个能登录的效果
vue实现一个账号在同一时间只有一个能登录的效果
169 0
|
9月前
|
Android开发
【通讯录教程】苹果安卓鸿蒙系统通用,如何大批量导入手机号码到手机的通讯录,下面教你方法,只需1分钟搞定几万个号码的导入手机电话本
该文介绍了一种快速批量导入手机通讯录的方法,适用于处理大量手机号的需求,如微商管理、客户资料整理等。在QQ同步助手开始收费后,提供了免费的替代方案。步骤包括:下载批量导入软件(链接提供腾讯云盘和百度网盘地址),清空通讯录(非必需),制作符合格式的通讯录文件,并按操作系统(苹果、安卓或鸿蒙)进行导入。整个过程只需1分钟,简便快捷。
738 2
|
8月前
|
前端开发 JavaScript 安全
WebAssembly技术的出现为我们提供了一种全新的解决方案,开启了高性能网络应用的新时代
【6月更文挑战第10天】WebAssembly是高性能网络应用的新时代技术,它是一种虚拟机格式,允许C/C++等语言编译成二进制格式在Web浏览器中运行。具备高性能、高可移植性和良好安全性,适用于游戏开发、图形处理、计算机视觉等领域。随着技术进步,WebAssembly将支持更多语言,结合低代码平台简化开发,但需解决编译优化和安全性等问题。它正重塑Web应用的未来,开启高性能应用新时代。
81 0
|
9月前
|
Linux 开发工具
【项目--Hi3559A】如何在Hi3559A上运行自己的yolov3模型(修改类别、网络结构)
【项目--Hi3559A】如何在Hi3559A上运行自己的yolov3模型(修改类别、网络结构)
133 0
|
9月前
|
前端开发 JavaScript 开发工具
如何将网页封装成APP:一步步教你在线生成APP
随着移动互联网的发展,APP已经成为用户获取信息和服务的主要渠道,而企业和个人也纷纷加入APP开发的行列。但对于那些没有编程技能的人来说,想要开发一个APP仍然是很困难的事情。本文将介绍一种在线生成APP的方法,将网页封装成APP,无需编程经验,只需简单操作即可生成属于自己的APP。
|
Java API Spring
Spring Boot + MDC 实现全链路调用日志跟踪,这才叫优雅。。(上)
Spring Boot + MDC 实现全链路调用日志跟踪,这才叫优雅。。(上)
949 0

热门文章

最新文章