首页 > 其他分享 >数据结构:顺序表

数据结构:顺序表

时间:2024-09-20 20:54:28浏览次数:3  
标签:ps arr 顺序 int void SL 数据结构

顺序表

顺序表的概念与结构

概念:顺序表就是在内存中申请一段连续的空间来存放我们需要存放的数据,一般使用数组的方法来实现。
那顺序表跟数组有什么区别?
他们的本质是一样的,都是使用数组来存放数据。
顺序表相当于数组的加工与包装。
就好比我们下馆子吃的清炒西兰花,在米其林餐厅就会通过摆盘与封装,改个名字叫绿野仙踪,使其看起来更加高大上。
但是我们不能说顺序表就是数组,他们是不等价的,只能说底层结构采用的是数组的方式来实现我们的目的。

静态顺序表

我们学习C语言,肯定知道静态内存或者动态内存。
那静态顺序表也一样,就是利用定长数组来存放数据,它的空间在确定之后是不能随便更改的。

#ifndef __SEQLIST_H_//防止预编译重复个定义
#define __SEQLIST_H_
typedef int SLDateType//给数据类型重定义,方便后面更改数据类型
typedef struct SeqList
{
	SLDateType arr[10];//变长数组
	int size;//数组内有效元素个数
};SL
#endif

动态顺序表

之前C语言中学习过动态内存管理,里面有个函数叫realloc:
它的作用是给动态申请的内存追加空间,动态顺序表就可以通过他来实现。

#ifndef __SEQLIST_H_//防止预编译重复个定义
#define __SEQLIST_H_
typedef int SLDateType//给数据类型重定义,方便后面更改数据类型
typedef struct SeqList
{
	SLDateType* arr;//这里改为指针,动态内存开辟成功后首地址给他
	int size;//数组内有效元素个数
};SL
#endif

动态顺序表的基本只是就介绍完了,接下来我们来实现一下动态顺序表的功能。

动态顺序表的实现

用SeqList,h头文件声明一些动态顺序表的功能函数,SeqList.c文件实现功能函数的编写,最后在test.c文件里面测试编译。

SeqList.h的创建

#ifndef __SEQLIST_H_//防止预编译重复个定义
#define __SEQLIST_H_
typedef int SLDateType//给数据类型重定义,方便后面更改数据类型
typedef struct SeqList//创建一个结构体来存放动态顺序表的起始地址
//有效数据个数以及现在的内存大小
{
	SLDateType* arr;//这里改为指针,动态内存开辟成功后首地址给他
	int capacity//动态顺序表的内存大小
	int size;//数组内有效元素个数
};SL

void LS_Init(SL* ps);//初始化

void LS_Destry(SL* ps);//销毁动态内存

void SL_CheckCapacity(SL* ps);//检查动态内存是否已满

void SL_Print(SL* ps);//打印内存有效数据

void SL_PushBack(SL* ps, typedate x);//在末尾放置

void SL_PushFront(SL* ps, typedate x);//在第一个位置放置

void SL_Inser(SL* ps, typedate x, int pos);//在指定下标位置插入数据

void SL_PopBack(SL* ps);//删除最后一位数据

void SL_PopFront(SL* ps);//删除第一位数据

void SL_Deser(SL* ps, int pos);//删除指定位置数据

void Find(SL* ps, typedate x);//寻找某个数据的位置

#endif

测试文件(test.c)

#include "SeqList.h"

int main()
{
	SL s;
	return 0;
}

初始化动态顺序表(LS_Init)

void LS_Init(SL* ps)
{
	ps->arr=NULL;//给起始地址设置为空指针
	ps->size=ps->capacity=0;//数据有效个数与空间大小设为0;
}

动态顺序表的销毁(LS_Destry)

void LS_Destry(SL* ps)
{
	assert(ps->arr);//检查arr是否为NULL
	free(ps->arr);//释放动态开辟的空间
	ps->arr=NULL;
	ps->size=ps->capacity=0;//数据有效个数与空间大小设为0;
}

检查动态内存空间是否已满(SL_CheckCapacity)

这个地方我们要用到三目操作符,防止有的人忘记或者没接触过,再介绍一下它的用法:

int m = 表达式?x:y;

当表达式成立时,就将x的值赋值给m,表达式不成立就将y的值赋值给m。

这里我们用SL_CheckCapacity满足检查内存是否够用以及第一次创建内存的操作。

void SL_CheckCapacity(SL* ps)
{
	if (ps->size == ps->capacity)
	{
		int newdate = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		typedate * tmp=(typedate*)realloc(ps->arr, newdate * sizeof(typedate));
		assert(tmp);
		ps->arr = tmp;
		ps->capacity = newdate;
	}
}

如果数据有效个数与内存空间大小一致,那就代表空间使用完了,就需要申请空间,所以判断一下条件是否成立。
成立后如果内存大小为0,就说明是第一次创建,我们给newdate 赋值为4,在realloc函数中创建,如果不是第一次创建,就追加一倍的空间。

动态顺序表打印有效数据(SL_Print)

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

在末尾存放数据(SL_PushBack)

void SL_PushBack(SL* ps,typedate x)//在末位置添加数据
{
	assert(ps);
	SL_CheckCapacity(ps);
	ps->arr[ps->size++] = x;//放完数据后让数据有效个数+1
}

在起始位置添加有效数据(SL_PushFront)

要在第一个位置存放数据而不覆盖其他数据,就需要将数据整体后移一位。
根据最后一次移位条件:把下标为0的位置移到下标为1的位置可得for循环判定条件i>0,这样i最小是1。

void SL_PushFront(SL* ps, typedate x)//在起始位置添加有效数据
{
	assert(ps);
	SL_CheckCapacity(ps);
	for (int i =ps->size ; i>0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;
}

在指定位置添加数据(SL_Inser)

这个与在起始位置存放数据类似,将指定位置后面的数据后移一位即可。

void SL_Inser(SL* ps, typedate x,int pos)//在指定位置添加数据
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);//保证存放的位置在开辟的空间内部

	SL_CheckCapacity(ps);

	for (int i = ps->size; i>pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];  
	}
	ps->arr[pos] = x;
	ps->size++;
}

删除最后一位数据(SL_PopBack)

我们访问数据是基于有效数据个数访问的,直接将有效数据-1,这样我们便认为最后一个数据不是有效数据,就不会访问,跟删除效果一样。

void SL_PopBack(SL* ps)//删除最后一位数据
{
	assert(ps);
	ps->size--;
}

在起始位置删除数据(SL_PopFront)

我们将数据整体前移一位,让有效数据-1即可。

void SL_PopFront(SL* ps)
{
	assert(ps);                         //0 1 2 3
	for (int i = 0; i < ps->size-1; i++)//1 2 3 4
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

删除任意位置的数据(SL_Deser)

这个与在起始位置删除数据一样,将指定位置后面的数据往前移一位即可。

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

寻找内存中的某个数据的位置(Find)

void Find(SL* ps, typedate x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->arr[i] == x)
		{
			printf("找到了,下标是%d\n", i);
			return 0;
		}
	}
	printf("找不到\n");
}

测试顺序表(test.c)

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"

int main()
{
	SL s;
	LS_Init(&s);//初始化
	SL_PushBack(&s, 1);//末尾放置
	SL_PushBack(&s, 2);//末尾放置
	SL_PushBack(&s, 3);//末尾放置
	SL_PushFront(&s, 0);//起始放置
	SL_Print(&s);//打印,结果应该是0 1 2 3
	SL_Inser(&s, 9,2);//在下标2的位置存放9
	SL_Print(&s);//结果:0 1 9 2 3
	SL_PopBack(&s);//删除末位
	SL_Print(&s);//结果: 0 1 9 2
	SL_PopFront(&s);//删除起始位
	SL_Print(&s);// 1 9 2
	SL_Deser(&s, 1);//删除下表1的数据
	SL_Print(&s);//1 2
	Find(&s, 2);//寻找2的下标
	LS_Destry(&s);//下标应该是1
	return 0;
}

在这里插入图片描述
-----------------------------------------------------------分隔符
顺序表的基本操作就介绍完了,感谢各位的观看。
有错请在评论区指正,谢谢。

标签:ps,arr,顺序,int,void,SL,数据结构
From: https://blog.csdn.net/qq_71391318/article/details/142354666

相关文章

  • 数据结构 ——— 常见的时间复杂度计算例题(上篇)
    目录前言例题1:例题2:例题3:例题4:前言在上一章讲解了时间复杂度的概念,以及用大O的渐进表示法表示时间复杂度数据结构———算法的时间复杂度-CSDN博客接下来利用C语言代码的例题,更深一步的掌握用大O的渐进表示法表示代码的时间复杂度例题1:代码演示:voidFunc......
  • 8577 合并顺序表
    ###思路1.读取顺序表A和B的元素个数和元素。2.使用双指针法合并两个有序顺序表A和B到新的顺序表C。3.输出顺序表A、B和合并后的顺序表C。###伪代码1.读取顺序表A的元素个数和元素。2.读取顺序表B的元素个数和元素。3.初始化两个指针分别指向顺序表A和B的起始位......
  • C++顺序结构(2)
    一、变量、赋值语句与表达式1、天安门广场在北京市中心,它南北长880米,东西宽500米,试编一程序,计算天安门广场面积是多少平方米。点击查看代码1//试编程,计算天安门广场的面积是多少平方米2#include<iostream>//包含输入输出流头文件iostream3usingnamespacestd;......
  • en造数据结构与算法C# 用Unity实现简单的群组行为算法 之 对齐
    en造数据结构与算法C#用Unity实现简单的群组行为算法之聚集-CSDN博客en造数据结构与算法C#用Unity实现简单的群组行为算法之聚集-CSDN博客演示思路1.检测自然是沿用前两节的检测范围2.对齐朝向对齐朝向就是邻居鸟的forward加起来再除总数得到平均数3.对齐速度......
  • en造数据结构与算法C# 群组行为优化 和 头鸟控制
    实现:1.给鸟类随机播放随机动画使得每一只鸟扇翅膀的频率都不尽相同2.可以自行添加权重,并在最后 sumForce=separationForce+cohesionForce+alignmentForce;分别乘上相应权重,这样鸟就能快速飞行和转向辣usingSystem.Collections.Generic;usingUnityEngine;usingS......
  • 【学习笔记】数据结构(六 ①)
    树和二叉树(一)文章目录树和二叉树(一)6.1树(Tree)的定义和基本术语6.2二叉树6.2.1二叉树的定义1、斜树2、满二叉树3、完全二叉树4、二叉排序树5、平衡二叉树(AVL树)6、红黑树6.2.2二叉树的性质6.2.3二叉树的存储结构6.3遍历二叉树和线索二叉树6.3.1遍历二叉树......
  • Python中的树与图:构建复杂数据结构的艺术
    引言随着大数据时代的到来,我们面临的数据不再是简单的线性关系,而是错综复杂的网状结构。树和图正是用于表示这类复杂关系的最佳工具。树是一种特殊的图,它具有层次结构;而图则更加灵活,能够表达任意节点之间的连接关系。掌握树与图的实现方法,不仅有助于提高算法设计能力,还能为......
  • 基于Java中的SSM框架实现数据结构课堂考勤管理平台项目【项目源码+论文说明】
    基于java中的SSM框架实现数据结构课堂考勤管理平台演示【内附项目源码+LW说明】摘要高校的不断扩张让在校学生数量不断的增加,对于教师和管理人员的需求也在不断地增强,对日常的学生考勤管理的工作量也在日益增加,传统的人工点名签到的考勤管理模式已经给无法适用于当前高校......
  • 集合框架底层使用了什么数据结构
    1.是什么        集合框架(CollectionFramework)是Java标准库的一部分,它提供了一系列接口和实现类,用于处理不同类型的集合。这些集合可以用于存储和操作对象,如列表、集合、映射等。集合框架的底层数据结构是多种多样的,具体取决于集合实现类的选择。1.List(列表)Array......
  • java_day3_Scanner,顺序结构,选择结构(if,switch),循环结构(for,while),
    一、Scanner键盘录入:程序运行过程中,用户可以根据自己的需求输入参与运算的值实现键盘录入的步骤1、导包2、创建键盘录入对象3、调用方法实现键盘录入1)输入整数2)输入字符串publicclassScannerDemo1{publicstaticvoidmain(String[......