数据结构-顺序表

news2025/1/19 14:27:27

数据结构-顺序表

  • 线性表
  • 顺序表的概念和结构
    • 静态顺序表和动态顺序表
  • 接口的实现
    • 顺序表的初始化
    • 顺序表的打印
    • 顺序表的销毁
    • 顺序表的增容
    • 顺序表的尾插
    • 顺序表的尾删
    • 顺序表的头插
    • 顺序表的头删
    • 顺序表的任意位置插入
    • 顺序表的任意位置删除
    • 顺序表中元素的查找
  • 完整代码

线性表

线性表是n个具有相同特性的数据元素的有限序列。它是一种数据结构。常见的线性表有:顺序表,链表,栈,队列,字符串等。线性表在逻辑上是线性结构,也就是说,从逻辑的角度来看,它是连续的一条直线。但是在物理结构上不一定是连续的,通常以数组和链式结构的形式存储。这里我们主要了解顺序表。

顺序表的概念和结构

顺序表是用一段物理地址连续的存储单元依次存储元素的线性结构。一般情况下采用数组的形式进行存储。在数组上完成数组的增删查改。
在这里插入图片描述

顺序表一般可以分为静态顺序表和动态顺序表。

静态顺序表和动态顺序表

静态顺序表的数组长度是固定的。如下:

#define N 10000
typedef int SLDataType;
struct SeqList
{
	SLDataType a[N];
	int size;
};

这里#define 对数组的长度10000用N来替换;typedef对int数据类型重新定义为一个新的名字SLDataType;SeqList就是我们的顺序表,它包括数组和当前的数据表的长度size。

由于静态顺序表的数组大小是固定的,当数组大小不大时,数据增加,可能存放不下;当数组大小大的时候,又会造成空间的浪费。因此,静态顺序表不常用。常用动态顺序表,如下:

//动态
typedef int SLDataType;
#define INIT_CAPACITY 4


typedef struct SeqList
{
	SLDataType* a;
	int size;//当前数据的个数
	int capacity;//容量
}SL;

这里typedef对int数据类型重新定义为一个新的名字SLDataType;SeqList就是我们的顺序表,它包括SLDataType* a指针和当前的数据的个数size,顺序表的容量capacity;对顺序表struct SeqList数据类型重新定义为一个新的名字SL。

接口的实现

顺序表的初始化

初始化:malloc函数申请空间为数组所占用的空间,size置零,给定初始容量为4
这里我们采用指针进行函数传参。

#define INIT_CAPACITY 4
void SLInit(SL* ps)
{
	ps->a = (SLDataType*)malloc(sizeof(SLDataType*) * INIT_CAPACITY);
	if(ps->a == NULL)
	{
		perror("malloc fail");
		return ;
	}

	ps->size = 0;
	ps->capacity = INIT_CAPACITY;
}

顺序表的打印

顺序表的打印就是打印出数组中的元素

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

顺序表的销毁

动态空间释放,指针置NULL;变量归0

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

顺序表的增容

当元素个数size大于等于顺序表中的capacity时,就需要增容。
我们使用realloc函数对其增容,增容后,指针需要重新赋值,capacity变量值需要改变。

void SLCheckCapacity(SL* ps)
{
	if (ps->capacity == ps->size)
	{
		SLDataType* temp = (SLDataType*)realloc(ps->a, sizeof(SLDataType*) * ps->capacity * 2);
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}

		ps->a = temp;
		ps->capacity *= 2;
	}
}

顺序表的尾插

尾插比较简单,只需要size++后,给数组赋值即可。

void SLPushBack(SL* ps, SLDataType x)
{
	if (ps->capacity==ps->size)
	{
		SLDataType* temp = (SLDataType*)realloc(ps->a, sizeof(SLDataType*) * ps->capacity * 2);
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}

		ps->a = temp;
		ps->capacity *= 2;
	}//这里也可以直接调用SLCheckCapacity函数
	ps->a[ps->size++] = x;
}

顺序表的尾删

这里只需要size–动作,不需要去计较最后一个元素是否已从内存中清空;但是需要检查size,即顺序表中要存在数据。

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

顺序表的头插

在顺序表的头部插入数据,就是意为着所有的元素都要后移1位。如果从前面的元素开始移动数据,则会覆盖掉后面的元素。因此,我们从最后一个元素向后移动数据,一直到指针end指向0。动画如下:
在这里插入图片描述

void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	int end = ps->size - 1;
	while (end>=0)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[0] = x;
	ps->size++;


	//SLInsert(ps, 0, x);
}

顺序表的头删

在顺序表的头部删除数据,只需要将后面的元素逐步覆盖掉前一个元素,指针从1开始,到size-1结束。动画如下:
在这里插入图片描述

void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size>0);
	int begin = 1;
	while (begin<ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}
	ps->size--;


	//SLErase(ps, 0);
}

顺序表的任意位置插入

和头插的思想一样,在被插入的位置和以后的位置的元素都要后移1位,仍然是从最后一个元素后移,指针由size-1变化到pos。动画如下:
在这里插入图片描述

void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos>=0&&pos<=ps->size);
	SLCheckCapacity(ps);
	int end = ps->size - 1;
	while (end>=pos)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}

因为是任意位置的插入,因此,对于头插和尾插都可以用SLInsert函数实现,如下:

SLInsert(ps,ps->size,x);//尾插
SLInsert(ps, 0, x);//头插

顺序表的任意位置删除

与头删的思想一样,只需要将被删除位置后面的元素依次覆盖掉前面的元素。动画如下:
在这里插入图片描述

void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos>=0&&pos<ps->size);
	int begin = pos + 1;
	while (begin<ps->size)
	{
		ps->a[begin-1] = ps->a[begin];
		begin++;
	}
	ps->size--;
}

因为是任意位置的删除,所以头删和尾删也可以用SLErase函数表示,如下:

SLErase(ps,ps->size-1);//尾删
SLErase(ps, 0);//头删

顺序表中元素的查找

这里采用遍历的方法来查找元素,如下:

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

	return -1;
}

完整代码

主程序:

#define _CRT_SECURE_NO_WARNINGS 1

#include "SeqList.h"

void TestSeList1()
{
	SL s;
	SLInit(&s);
	SLPushBack(&s, 1);
	SLPushBack(&s, 2);
	SLPushBack(&s, 4);
	SLPushBack(&s, 6);
	SLPushBack(&s, 8);
	SLPopBack(&s);
	SLPopBack(&s);
	SLPopBack(&s);

	SLPushFront(&s, -1);
	SLPushFront(&s, -2);
	SLPushFront(&s, -3);
	SLPopFront(&s);
	SLPopFront(&s);
	SLPopFront(&s);

	SLInsert(&s, 1, 11);
	SLInsert(&s, 2, 12);
	SLErase(&s, 2);
	SLErase(&s, 1);

	SLPushBack(&s, 100);
	SLPushFront(&s, -100);
	SLPopBack(&s);
	SLPopFront(&s);

	int ret=SLFind(&s,1);
	printf("%d\n",ret);


	SLPrint(&s);
	SLDestroy(&s);

}
int main()
{
	TestSeList1();

	return 0;
}

函数的定义

#define _CRT_SECURE_NO_WARNINGS 1

#include "SeqList.h"

void SLInit(SL* ps)
{
	ps->a = (SLDataType*)malloc(sizeof(SLDataType*) * INIT_CAPACITY);
	if(ps->a == NULL)
	{
		perror("malloc fail");
		return ;
	}

	ps->size = 0;
	ps->capacity = INIT_CAPACITY;
}

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

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

void SLCheckCapacity(SL* ps)
{
	if (ps->capacity == ps->size)
	{
		SLDataType* temp = (SLDataType*)realloc(ps->a, sizeof(SLDataType*) * ps->capacity * 2);
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}

		ps->a = temp;
		ps->capacity *= 2;
	}
}


void SLPushBack(SL* ps, SLDataType x)
{
	if (ps->capacity==ps->size)
	{
		SLDataType* temp = (SLDataType*)realloc(ps->a, sizeof(SLDataType*) * ps->capacity * 2);
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}

		ps->a = temp;
		ps->capacity *= 2;
	}
	ps->a[ps->size++] = x;


	//SLInsert(ps,ps->size,x);
}

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


	//SLErase(ps,ps->size-1);
}


void SLPushFront(SL* ps, SLDataType x)
{
	//assert(ps);
	//SLCheckCapacity(ps);
	//int end = ps->size - 1;
	//while (end>=0)
	//{
	//	ps->a[end + 1] = ps->a[end];
	//	end--;
	//}
	//ps->a[0] = x;
	//ps->size++;


	SLInsert(ps, 0, x);
}

void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size>0);
	int begin = 1;
	while (begin<ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}
	ps->size--;


	//SLErase(ps, 0);
}

void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos>=0&&pos<=ps->size);
	SLCheckCapacity(ps);
	int end = ps->size - 1;
	while (end>=pos)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}

void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos>=0&&pos<ps->size);
	int begin = pos + 1;
	while (begin<ps->size)
	{
		ps->a[begin-1] = ps->a[begin];
		begin++;
	}
	ps->size--;
}

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

	return -1;
}

函数的声明

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
//静态
//#define N 10000
//typedef int SLDataType;
//struct SeqList
//{
//	SLDataType a[N];
//	int size;
//};

//动态
typedef int SLDataType;
#define INIT_CAPACITY 4


typedef struct SeqList
{
	SLDataType* a;
	int size;//当前数据的个数
	int capacity;//容量
}SL;

void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
void SLCheckCapacity(SL* ps);


void SLPushBack(SL* ps, SLDataType x);//尾插
void SLPopBack(SL* ps);//尾删
void SLPushFront(SL* ps,SLDataType x);//头插
void SLPopFront(SL* ps);//头删
void SLInsert(SL* ps,int pos,SLDataType x);//任意位置的插入
void SLErase(SL* ps,int pos);//任意位置的删除
int SLFind(SL* ps, SLDataType x);//查找元素

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/575955.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据包伪造替换、会话劫持、https劫持之探索和测试

&#xff08;一&#xff09;数据包替换攻击 该攻击过程如下&#xff1a;伪造服务器响应客户端的数据包。监听客户端的数据包&#xff0c;用预先伪造的数据包&#xff0c;伪装成服务器返回的数据发送给客户端。 因为攻击者跟目标在同一个局域网&#xff0c;所以攻击者发送的数…

无监督学习——k均值

文章目录 聚类k均值代码实现1. 引入依赖2. 数据加载3. 算法实现4. 测试 无监督学习重要的应用有两类&#xff1a;聚类、降维。 聚类&#xff1a; k均值 基于密度的聚类 最大期望聚类 降维&#xff1a; 潜语义分析&#xff08;LSA&#xff09; 主成分分析&#xff08;PCA&a…

AcWing算法提高课-1.3.11二维费用的背包问题

宣传一下算法提高课整理 <— CSDN个人主页&#xff1a;更好的阅读体验 <— 本题链接&#xff08;AcWing&#xff09; 点这里 题目描述 有 N N N 件物品和一个容量是 V V V 的背包&#xff0c;背包能承受的最大重量是 M M M。 每件物品只能用一次。体积是 v i v_…

【C++系列P3】‘类与对象‘-三部曲——[精讲](1/3)

前言 大家好吖&#xff0c;欢迎来到 YY 滴 C系列 &#xff0c;热烈欢迎&#xff01; 【 类与对象-三部曲】的大纲主要内容如下&#xff1a; 如标题所示&#xff0c;本章是【 类与对象-三部曲】三章中的第一章节——基础知识章节&#xff0c;主要内容如下&#xff1a; 目录 一.…

apache-jmeter:点击可视化界面闪退和中文乱码Failed to write core dump

目录 1、点击界面闪退1.1、问题描述1.2、解决方法 2、处理返回结果乱码问题3、中文界面乱码3.1、问题描述3.2、解决方法 1、点击界面闪退 1.1、问题描述 Java运行环境 $ java -version java version "1.8.0_251" Java(TM) SE Runtime Environment (build 1.8.0_25…

学生成绩管理系统(C语言有结构体实现)

目录标 一、要实现的功能1.首次运行2. 成绩录入3. 显示录入的成绩4. 计算平均值5. 对平均分排序6. 查询学生成绩7. 清屏8. 显示帮助菜单9. 系统 二、实现代码&#xff08;一&#xff09;所有代码在一个文件&#xff08;v1&#xff09;&#xff08;二&#xff09;分文件编写&…

全志V3S嵌入式驱动开发(制作根文件系统)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 根文件系统是嵌入式开发很重要的一环。目前对于大多数soc来说&#xff0c;制作嵌入式系统就是配置buildroot文件。今天使用的buildroot版本是build…

一个字牛!腾讯大牛把《数据结构与算法》讲透了,带源码笔记

话不多说&#xff0c;直接先上图 经历过校招的人都知道&#xff0c;算法和数据结构都是不可避免的。 在笔试的时候&#xff0c;最主要的就是靠算法题。像拼多多、头条这种大公司&#xff0c;上来就来几道算法题&#xff0c;如果你没AC出来&#xff0c;面试机会都没有。 在面试…

上午在改BUG,下午就被通知优化了····

前段时间&#xff0c;爱奇艺被曝出大规模裁员的消息&#xff0c;裁员比例为20%-40%&#xff0c;对此&#xff0c;爱奇艺并未回应。有多位爱奇艺员工向深燃证实了裁员消息。“现在&#xff0c;空了好些工位。”一位爱奇艺员工表示。据他了解&#xff0c;仅爱奇艺文学&#xff0c…

21天学会C++:Day5----引用

CSDN的uu们&#xff0c;大家好。这里是C入门的第五讲。 座右铭&#xff1a;前路坎坷&#xff0c;披荆斩棘&#xff0c;扶摇直上。 博客主页&#xff1a; 姬如祎 收录专栏&#xff1a;C专题 目录 1. 知识引入 2. 引用的特性 2.1 引用在定义时必须初始化 2.2 一个变量可以有多…

车间静电消除不掉?静电接地桩来帮忙!

静电接地桩的原理是通过将金属导体与地面相连&#xff0c;以便在设备运行时能够稳定地将静电荷自然地释放到地面中&#xff0c;从而保护人员和设备不受到静电的危害。 在工业生产中&#xff0c;静电容易在人体和物体表面积聚&#xff0c;如果不及时地排放处理会对人员和设备造…

【算法】简单讲解如何使用两个栈实现一个队列

文章目录 什么是栈和队列&#xff1f;设计思路代码实现 什么是栈和队列&#xff1f; 栈和队列其实大家基本都知道是什么&#xff0c;或者说&#xff0c;最基本的&#xff0c;他们的特性我们是知道的。 栈是一种FILO先进后出的数据结构&#xff0c;队列是一种FIFO先进先出的数据…

SRS流媒体服务器 ---- st-thread框架

1.使用st-thread 我们用一个简单的demo研究一下st框架。 #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include "st.h"static void *_thread(void *arg) {printf("thread: %lu\n", pthread_self());return NULL; }i…

实例6.1 六度空间

“六度空间”理论又称作“六度分隔&#xff08;Six Degrees of Separation&#xff09;”理论。这个理论可以通俗地阐述为&#xff1a;“你和任何一个陌生人之间所间隔的人不会超过六个&#xff0c;也就是说&#xff0c;最多通过五个人你就能够认识任何一个陌生人。”如图1所示…

MySql MVCC 详解

注意以下操作都是以InnoDB引擎为操作基准。 一&#xff0c;前置知识准备 1&#xff0c;MVCC简介 MVCC 是多版本并发控制&#xff08;Multiversion Concurrency Control&#xff09;的缩写。它是一种数据库事务管理技术&#xff0c;用于解决并发访问数据库的问题。MVCC 通过创…

ROS学习——Gazebo中搭建模型并显示

一、打开gazebo搭建模型 gazebo 在gazebo界面左上角点击“Edit”——>"Building Editor"进入下图的模型搭建界面。可以自己利用左边的材料搭建模型。 点击墙壁之类的物品&#xff0c;右键&#xff0c;点击“Open Wall Inspector”按钮&#xff0c;就会出现可以调…

jmeter做接口压力测试_jmeter接口性能测试

jmeter是apache公司基于java开发的一款开源压力测试工具&#xff0c;体积小&#xff0c;功能全&#xff0c;使用方便&#xff0c;是一个比较轻量级的测试工具&#xff0c;使用起来非常简单。因为jmeter是java开发的&#xff0c;所以运行的时候必须先要安装jdk才可以。jmeter是免…

第11届蓝桥杯Scratch省赛真题集锦

编程题 第 1 题 问答题 对对碰 题目说明 编程实现 对对碰 两两相同的一共四张扣下的纸牌&#xff0c;每次先后翻开两张。如果两张一样就消失&#xff0c;如果两张不一样就重新扣下。当舞台上所有纸牌都消失&#xff0c;就过关了 .1)创建四个经牌角色&#xff0c;每张纸牌…

linuxOPS基础_Linux文件管理

Linux下文件命名规则 可以使用哪些字符&#xff1f; 理论上除了字符“/”之外&#xff0c;所有的字符都可以使用&#xff0c;但是要注意&#xff0c;在目录名或文件名中&#xff0c;不建议使用某些特殊字符&#xff0c;例如&#xff0c; <、>、&#xff1f;、* 等&…

表单重复提交:

1. 表单重复提交原因 当用户提交完请求&#xff0c;浏览器会记录最后一次请求的全部信息。用户按下功能键F5&#xff0c;就会发起浏览器记录的最后一次请求。如果最后一次请求为添加操作&#xff0c;那么此时刷新按钮就会再次提交数据&#xff0c;造成表单重复提交。 2. 表单…