【数据结构】顺序表(上)

news/2024/11/9 0:29:21/

所属专栏:初始数据结构
博主首页:初阳785
代码托管:chuyang785>
感谢大家的支持,您的点赞和关注是对我最大的支持!!!
博主也会更加的努力,创作出更优质的博文!!
关注我,关注我,关注我,重要的事情说三遍!!!!!!!!

【数据结构】顺序表(上)

  • 1.线性表
  • 1.1概念
  • 2.顺序表
    • 2.1顺序表的概念及结构
  • 3.使用顺序表实现接口
    • 3.1 seqList.h头文件展示
    • 3.2 seqList.c源文件展示
    • 3.3 test.c源文件展示
    • 3.4初始化结构体
    • 3.5检查容量
    • 3.6尾插
    • 3.7数据展示
    • 3.8尾删
    • 3.9头插
    • 3.10头删
  • 4.自主设计

1.线性表

1.1概念

概念:线性表(linear list)是n个具有相同特性的数据元素的有限序列。
线性表是一种实际中广泛使用的数据结构,常见的线性表:顺序表,链表,
栈,队列,字符串……线性表在逻辑上是线性结构的,也就是说是连续的一条直线。但是在物理结构上
并不是连续的,线性表在物理上存储时,通常以数组和链式结构的形式储存。顺序表的本质就是数组,但是不同于数组的时顺序表分动态的和静态的。
而且顺序表存放数据必须是连续的,数组没有要求。

在这里插入图片描述
看起来有点想数组。

2.顺序表

2.1顺序表的概念及结构

顺序表是用一段物理地址连续的存放单元,依次存储数据元素的线性结构,
一般情况先采用数组存储,在数组上完成数据的增删查改。顺序表就是数组,但是在数组的基础上它还要求数据是从头开始连续存储的,不能跳跃间隔。

3.使用顺序表实现接口

所谓接口,就相当于已经设计好的程序,如果要用的话就是接调用这个接口。
你可以这样理解,我们在拧螺丝的时候可能需要不同的工具头,可能是平头的,也可能是交叉的,而我们如果想使用的话只需要把不同的工具头套在我们把手上使用即可,这些工具头就是我们的接口。

3.1 seqList.h头文件展示

#pragma once //防止头文件被重复包含
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>typedef int SLDataType;
typedef struct SeqList
{SLDataType* a;int size;// 表示数组中存储了多少个数据int capacity;//数组实际能存放数据的空间间容量是多大
}SL;// 接口函数--命名风格是跟着STL走的
//初始化
void SeqListPrint(SL* ps);
//打印数据
void SeqListInit(SL* ps);
//销毁空间
void SeqListDestory(SL* ps);//检查容量
void SeqListCheckCapacity(SL* ps);
//尾插
void SeqListPushBack(SL* ps, SLDataType x);
//尾删
void SeqListPopBack(SL* ps);
//头插
void SeqListPushFront(SL* ps, SLDataType x);
//头删
void SeqListPopFront(SL* ps);

3.2 seqList.c源文件展示

#include "seqList.h"//打印数据
void SeqListPrint(SL* ps)
{int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}//初始化
void SeqListInit(SL* ps)
{ps->a = NULL;ps->size = ps->capacity = 0;
}//空间回收
void SeqListDestory(SL* ps)
{free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0;
}//检查容量
void SeqListCheckCapacity(SL* ps)
{//空间不足,扩容。//SeqListCheckCapacity(ps);if (ps->size == ps->capacity)//没空间或者空间满了{int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//ps->capacity = ps->capacity == 0 ? 4 : ps->capacity * 2;// //if (ps->capacity == 0)//{//	ps->capacity = 4;//}//else//{//	ps->capacity = ps->capacity * 2;//}SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL){printf("relloc fial\n");exit(-1);//退出函数}ps->a = tmp;ps->capacity = newcapacity;}
}//尾插
void SeqListPushBack(SL* ps, SLDataType x)
{SeqListCheckCapacity(ps);ps->a[ps->size] = x;//printf("%d ", ps->a[ps->size]);ps->size++;
} //尾删
void SeqListPopBack(SL* ps)
{//温柔的处理方式//if (ps->size > 0)//{//	ps->size--;//}//暴力的处理方式assert(ps->size > 0);ps->size--;
}
//头插
void SeqListPushFront(SL* ps, SLDataType x)
{//判断是否满了SeqListCheckCapacity(ps);int end = 0;for (end = ps->size - 1; end >= 0; end--){ps->a[end+1] = ps->a[end];}ps->a[0] = x;ps->size++;
}
//头删
void SeqListPopFront(SL* ps)
{assert(ps->size > 0);int bigan = 1;for (bigan = 1; bigan < ps->size; bigan++){ps->a[bigan-1] = ps->a[bigan];}ps->size--;
}

3.3 test.c源文件展示

本章节主要是实现接口函数的,我们的test.c源文件只是用来检测我们的接口函数是否正确,所以不做要求。

3.4初始化结构体

typedef int SLDataType;
typedef struct SeqList
{SLDataType* a;int size;// 表示数组中存储了多少个数据int capacity;//数组实际能存放数据的空间间容量是多大
}SL;

注意:这我们用了一个关键字typedef,typedef int SLDataType这里我我们将int进行重命名位
SLDataType,应为我们这是在实现接口,我们的接口要尽量的通用,这里我们要设计的数据类型可能不是int,肯能是double也可能是其他的类型的,所以如果我们要改的话只要在关键字那里改就行了,就会很方便。

3.5检查容量

void SeqListCheckCapacity(SL* ps)
{//空间不足,扩容。//SeqListCheckCapacity(ps);if (ps->size == ps->capacity)//没空间或者空间满了{int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//这里先给4给大小的容量//ps->capacity = ps->capacity == 0 ? 4 : ps->capacity * 2;上面的三目操作发等同以下//if (ps->capacity == 0)//{//	ps->capacity = 4;//}//else//{//	ps->capacity = ps->capacity * 2;//}SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL){printf("relloc fial\n");exit(-1);//退出函数}ps->a = tmp;ps->capacity = newcapacity;}
}

这里我们使用到了realloc动态内存开辟函数,realloc函数有个特点就是内存不够的时候它可以继续开辟内存,而且当我们我们还没有开辟内存的时候,第一次开辟内存等同于malloc。

3.6尾插

void SeqListPushFront(SL* ps, SLDataType x)
{//判断是否满了SeqListCheckCapacity(ps);int end = 0;for (end = ps->size - 1; end >= 0; end--){ps->a[end+1] = ps->a[end];}ps->a[0] = x;ps->size++;
}

这里最关键的是判断容量,如果满了我们就扩容。

3.7数据展示

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

这个就没什么好说的,一个for循环就解决了。

3.8尾删

void SeqListPopBack(SL* ps)
{//温柔的处理方式//if (ps->size > 0)//{//	ps->size--;//}//暴力的处理方式assert(ps->size > 0);ps->size--;
}

我们的查询数据的原理其实和数组是一样的,所以只要我们遍历不到我们想要的数据的下标就打印不出来,就等同于删除数据了。但是这里我们要注意的是如果我们的数据已经删完了,我们的ps->size就不能继续–下去了,不然就会得到负数,显然会出现错误。

3.9头插

void SeqListPushFront(SL* ps, SLDataType x)
{//判断是否满了SeqListCheckCapacity(ps);int end = 0;for (end = ps->size - 1; end >= 0; end--){ps->a[end+1] = ps->a[end];}ps->a[0] = x;ps->size++;
}

在进行头插的时候我们想到的办法就是平移法:
在这里插入图片描述
就是我们把现有的数据整体的网后平移一个位置,同时size++(还有就是别忘记判断容量)然后再在得一个位置插入我们的数据就行了。

3.10头删

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

在进行头删的时候我们想到的办法就是平移法:
在这里插入图片描述
就是把后后面的数据整体的向前推进一个位置,同时我们的size–;同样的也别忘记判断是否删完了。

4.自主设计

写到这里相信看到这的小伙伴们对我们的接口函数已经有基本的了解了,我们可以自己设计一些接口函数在这里我就给小伙伴们带来了三个个接口函数的设计:

  1. 给定一个下标要求查找数据,找到了返回下标否则返回-1。
  2. 给定一个下标要求在这个下标插入数据。
  3. 给定一个下标要求在这个下标删除数据。
    函数定义:
//找到x并返回它的下标,找不到返回-1
int SeqListFind(SL* ps, SLDataType x);
//给定一个位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x);
//给定一个位置删除
void SeeqListErase(SL* ps, int pos);

小伙伴们动起手来吧!!!!!!
我们会在下一节进行详细的讲解。


http://www.ppmy.cn/news/42762.html

相关文章

Centos Stream 9 图文详细安装记录

1. 下载镜像文件ISO 官方&#xff1a; https://mirror.stream.centos.org/9-stream/BaseOS/x86_64/iso/ 清华&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/centos-stream/9-stream/BaseOS/x86_64/iso/ 阿里云&#xff1a;https://mirrors.aliyun.com/centos-stream/9-st…

【C++STL精讲】vector的模拟实现

文章目录&#x1f490;专栏导读&#x1f490;文章导读&#x1f337;定义vector类&#x1f337;各成员函数的实现&#x1f33a;构造函数&#x1f33a;迭代器&#x1f33a;size与capacity——求大小与容量&#x1f33a;reserve——扩容关于reserve中的深浅拷贝问题&#x1f33a;r…

事务的隔离级别和传播行为

什么是事务&#xff1f; 事务&#xff1a;是数据库操作的最小工作单元&#xff0c;是作为单个逻辑工作单元执行的一系列操作&#xff1b;这些操作作为一个整体一起向系统提交&#xff0c;要么都执行、要么都不执行&#xff1b;事务是一组不可再分割的操作集合&#xff08;工作逻…

JavaWeb——synchronized详解

目录 一、特性 1、互斥性 2、不可中断性 3、可重入性 二、使用 1、修饰普通方法 2、修饰静态方法 3、修饰代码块 三、锁机制 一、特性 1、互斥性 当线程进入synchronized修饰的代码块时&#xff0c;就相当于加锁。当线程退出synchronized修饰的代码块时&#xff0c;就…

恒生电子面试题总结

CPU突然飙升&#xff0c;如何排查 1.监控cpu运行状态&#xff0c;显示进程运行信息列表 top -c 2. 按CPU使用率排序&#xff0c;键入大写的P P 3.用 top -Hp 命令查看占用 CPU 最高的线程 上一步用 top命令找到了那个 Java 进程。那一个进程中有那么多线程&#xff0c;不可…

Flutter 路由

前言&#xff1a; 路由的核心就是一个路由映射表&#xff0c;比如login 映射到 LoginPage,有了这样的映射&#xff0c;就可以根据名字去找寻对应的页面。 在Flutter 中&#xff0c;路由管理主要有两个类 Route 和 Navigator 一 Route 在Flutter 中&#xff0c;一个页面要想…

【2404. 出现最频繁的偶数元素】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个整数数组 nums &#xff0c;返回出现最频繁的偶数元素。 如果存在多个满足条件的元素&#xff0c;只需要返回 最小 的一个。如果不存在这样的元素&#xff0c;返回 -1 。 示例 1&#xff1…

https是什么?

HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09;是基于HTTP协议的安全版本&#xff0c;它使用SSL/TLS协议对数据进行加密和身份验证&#xff0c;从而保证通信的安全性和完整性。 HTTPS和HTTP的区别&#xff1a; 安全性&#xff1a;HTTPS通过SSL/TLS协议对数…