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

数据结构--顺序表

时间:2024-08-17 23:27:37浏览次数:13  
标签:arr 顺序 -- void int SL 数据结构 size

目录

一、引言

二、顺序表的基本概念与结构

1.概念

2.基本结构

三、顺序表的分类

四、动态顺序表的实现 

1.结构定义

2.相关功能实现

1.初始化

2.销毁

3.扩容

4.打印 

5.头插

6.尾插 

7.头删 

8.尾删 

9.指定插入 

10.指定删除 

11.查找 

 五、完整代码

1.SeqList.h

2.SeqList.c 

3.test.c

六、总结


一、引言

在计算机科学中,数据结构是一种存储和组织数据的方式,它使得数据的插入、删除和访问变得更加高效。顺序表(Array List)是一种基本的数据结构,它在内存中连续存储元素,为我们提供了操作数据的一种简单而有效的方法。本文将介绍顺序表的基本概念、分类,并展示如何在C语言中实现动态顺序表。

二、顺序表的基本概念与结构

1.概念

顺序表(也称为线性表)是一种线性数据结构,其中元素按照顺序在内存中连续存储。它的主要特点包括:
连续存储:所有元素在内存中占据一块连续的空间。
索引访问:可以通过索引快速访问任意元素。
固定大小:在静态实现中,顺序表的大小在创建时确定,无法动态调整。

• 顺序表和数组的区别 ◦ 顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝

2.基本结构

在C语言中,顺序表通常用一个数组来实现。以下是一个顺序表的基本结构:

//静态顺序表
typedef int DataType;重定义类型名字
#define MAX_SIZE 100
typedef struct {
    DataType data[MAX_SIZE];//定长数组
    int size; // 有效数据个数
} SL;

三、顺序表的分类

顺序表可以根据其存储方式和大小变化的特性分为以下几类:

静态顺序表

定义:使用静态数组实现的顺序表,其存储空间在编译时分配,大小固定不变。
特点:
空间分配在栈区或全局数据区。
容量固定,不易扩展。

动态顺序表

定义:使用动态数组实现的顺序表,其存储空间在运行时动态分配,可以根据需要进行扩展或缩减。
特点:
空间分配在堆区。
容量可变,通过 malloc 、 realloc 和 free 等操作进行管理。

四、动态顺序表的实现 

1.结构定义

typedef struct SeqList
{
	DataType* arr;
	int size;//有效数据个数
	int capacity;//容量
}SL;

2.相关功能实现

1.初始化

void SLInit(SL* p)
{
	p->arr = NULL;
	p->size = p->capacity = 0;
}

2.销毁

void SLDestory(SL* p)
{
	if (p->arr)
	{
		free(p->arr);
	}
	p->arr = NULL;
	p->size = p->capacity = 0;
}

3.扩容

void checkcapacity(SL*p)
{
	if (p->size == p->capacity)
	{
		int newcapacity = p->capacity == 0 ? 4 : 2 * p->capacity;
		DataType*tmp= (DataType*)realloc(p->arr,newcapacity * sizeof(DataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(1);
		}
		//空间申请成功
		p->arr = tmp;
		p->capacity = newcapacity;
	}
}

4.打印 

void SLPrint(SL s)
{
	for (int i = 0; i < s.size; i++)
	{
		printf("%d", s.arr[i]);
	}
}

5.头插

void SLPushHead(SL* p, DataType x)
{
	assert(p);
	checkcapacity(p);
	for (int i = p->size; i>=1; i--)
	{
		p->arr[i] = p->arr[i - 1];
	}
	p->arr[0] = x;
	p->size++;
}

6.尾插 

void SLPushBack(SL* p, DataType x)
{
	assert(p);
	checkcapacity(p);
	p->arr[p->size++] = x;
}

7.头删 

void SLDelHead(SL* p)
{
	assert(p);
	assert(p->size);//顺序表不为空
	for (int i = 1; i <=p->size-1; i++)
	{
		p->arr[i - 1] = p->arr[i];
	}
	p->size--;

}

8.尾删 

void SLDelBack(SL* p)
{
	assert(p);
	assert(p->size);//顺序表不为空
	(p->size)--;
}

9.指定插入 

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

10.指定删除 

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

11.查找 

int  SLFind(SL *p, DataType x)
{
	assert(p);
	for (int i = 0; i < p->size; i++)
	{
		if (p->arr[i]==x)
		{
			return i;//找到了
		}
	}
	return -1;//没有找到
}

 五、完整代码

1.SeqList.h

该部分放顺序表结构定义、函数的声明

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
//动态顺序表
typedef struct SeqList
{
	DataType* arr;
	int size;//有效数据个数
	int capacity;//容量
}SL;

//初始化顺序表
void SLInit(SL* p);
//销毁顺序表
void SLDestory(SL* p);
//打印顺序表
void SLPrint(SL s);
//顺序表头插
void SLPushHead(SL* p, DataType x);
//顺序表尾插
void SLPushBack(SL* p, DataType x);
//顺序表头删
void SLDelHead(SL* p);
//顺序表尾删
void SLDelBack(SL* p);
//在指定位置前插入数据
void SLInsert(SL* p, int pos, int x);
//删除指定位置的数据
void SLErase(SL* p, int pos);
//顺序表的查找
int  SLFind(SL* p, DataType x);

2.SeqList.c 

该部分是函数功能的实现,也就是上述第四点的代码

#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
//初始化顺序表
void SLInit(SL* p)
{
	p->arr = NULL;
	p->size = p->capacity = 0;
}
//销毁顺序表
void SLDestory(SL* p)
{
	if (p->arr)
	{
		free(p->arr);
	}
	p->arr = NULL;
	p->size = p->capacity = 0;
}
//检查容量判断是否扩容
void checkcapacity(SL*p)
{
	if (p->size == p->capacity)
	{
		int newcapacity = p->capacity == 0 ? 4 : 2 * p->capacity;
		DataType*tmp= (DataType*)realloc(p->arr,newcapacity * sizeof(DataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(1);
		}
		//空间申请成功
		p->arr = tmp;
		p->capacity = newcapacity;
	}
}
//打印顺序表
void SLPrint(SL s)
{
	for (int i = 0; i < s.size; i++)
	{
		printf("%d", s.arr[i]);
	}
}
//顺序表头插
void SLPushHead(SL* p, DataType x)
{
	assert(p);
	checkcapacity(p);
	for (int i = p->size; i>=1; i--)
	{
		p->arr[i] = p->arr[i - 1];
	}
	p->arr[0] = x;
	p->size++;
}
//顺序表尾插
void SLPushBack(SL* p, DataType x)
{
	assert(p);
	checkcapacity(p);
	p->arr[p->size++] = x;
}
//顺序表头删
void SLDelHead(SL* p)
{
	assert(p);
	assert(p->size);//顺序表不为空
	for (int i = 1; i <=p->size-1; i++)
	{
		p->arr[i - 1] = p->arr[i];
	}
	p->size--;

}
//顺序表尾删
void SLDelBack(SL* p)
{
	assert(p);
	assert(p->size);//顺序表不为空
	(p->size)--;
}
//在指定位置前插入数据
void SLInsert(SL* p, int pos, DataType x)
{
	assert(p);
	assert(pos >= 0 && pos <=p->size);
	for (int i = p->size-1; i >=pos; i--)
	{
		p->arr[i + 1] = p->arr[i];
	}
	p->arr[pos] = x;
	p->size++;
}
//删除指定位置的数据
void SLErase(SL* p, int pos)
{
	assert(p);
	assert(pos >= 0 && pos < p->size);
	for (int i = pos; i <=p->size-2; i++)
	{
		p->arr[i] = p->arr[i+1];
	}
	p->size--;
}
//顺序表的查找
int  SLFind(SL *p, DataType x)
{
	assert(p);
	for (int i = 0; i < p->size; i++)
	{
		if (p->arr[i]==x)
		{
			return i;//找到了
		}
	}
	return -1;//没有找到
}

3.test.c

该部分用来测试我们写的函数(函数的调用),可以随便改

#define _CRT_SECURE_NO_WARNINGS
#include"SeqList.h"
void SLtest01()//测试
{
	SL sl;
	SLInit(&sl);
	//增删查改操作
	SLPushHead(&sl,1);//头插1      1
	SLPushHead(&sl,3);//头插3      31
	SLPushBack(&sl, 5);//尾插5     315
    SLInsert(&sl,3,7);//在下标为3的位置插入7    3157
	SLErase(&sl,2);//删除下标为2的数据     317
	SLPrint(sl);
	int find = SLFind(&sl, 3);
	if (find>=0)
	{
		printf("找到了,下标为%d\n", find);
	}
	else
	{
		printf("没有找到");
	}
	SLDestory(&sl);
}
int main()
{
	SLtest01();
	return 0;
}

六、总结

顺序表是一种简单而强大的数据结构,通过连续内存存储实现高效的随机访问。根据需要,我们可以选择静态或动态顺序表来适应不同的应用场景。动态顺序表通过动态调整大小,提供了更大的灵活性和效率。希望本文对你理解顺序表及其实现有所帮助!

 

标签:arr,顺序,--,void,int,SL,数据结构,size
From: https://blog.csdn.net/2302_81410974/article/details/141288093

相关文章

  • 【Verilog-CBB】开发与验证(6)——RS打拍器
    引言前面两篇文章分别给出了RS前向/后向打拍器的设计,分别可以优化valid和ready信号的时序。那么如果想要同时优化valid/ready时序则可以同时例化前向/后向打拍器。那么例化时谁在前谁在后呢?xilinx官网给出RS双向打拍器的结构框图,也该是后向打拍器在前,前向打拍器级联在后向......
  • 【STM32】寻迹小车项目复盘
    寻迹小车项目复盘前言复盘简述项目无思路,无大局观描述复盘项目无架构描述复盘下次项目改进思路DEBUG无思路前言博主近日首次完成了一个简单的循迹小车。但让我意外的是,在我上手如此简单的项目时,我的思路却十分混乱,开发过程毫无逻辑,虽说跌跌撞撞的做出来了,但效率低......
  • I/O多路转接之 select 与 poll
    目录一、select(一)初识select(二)理解select执行过程(三)socket就绪条件(四)select的特点(五)select缺点(六)select使用示例二、poll(一)poll函数接口(二)socket就绪条件(三)poll的优点(四)poll的缺点(五)poll使用示例在Linux系统中,I/O多路转接是一种重要的I/O模型(也称I/O多路复用),它......
  • D1-H Tinalinux 开发板 挂载U盘
    将U盘格式化成NFS格式 插入U盘到开发板HostUSB,会显示信息[4060.109026]usb1-1:USBdisconnect,devicenumber7[4139.330081]sunxi-ehci4200000.ehci1-controller:ehci_irq:highspeeddeviceconnect[4139.600007]usb1-1:newhigh-speedUSBdevicenumber8......
  • 五种IO模型
    目录一、五种IO模型(一)阻塞IO(二)非阻塞IO(三)信号驱动IO(四)IO多路转接(五)异步IO二、高级IO重要概念(一)同步通信与异步通信(二)阻塞与非阻塞理解这四者的关系在进行网络编程或文件操作时,IO模型的选择对程序的性能和效率有着重要的影响。本文将介绍五种IO模型,并详细讨论非阻......
  • ansible 变量优先级示例
    目录ansible变量优先级示例1.不是变量的变量2.角色默认值3.主机配置清单或动态脚本生成的groupvars4.主机配置清单group_vars/all5.剧本group_vars/all6主机配置清单group_vars/*7剧本group_vars/*8.主机清单文件or动态生成主机清单文件的主机变量9.主机清单文件h......
  • DataWhale AI夏令营-大模型微调-学习笔记3
     Task1:从零入门大模型微调一、问题概述从零入门大模型微调是Datawhale2024年AI夏令营第四期的学习活动(“大模型技术”方向),基于讯飞开放平台“星火大模型驱动阅读理解题库构建挑战赛”开展的实践学习。学习内容:基于讯飞大模型定制训练平台和spark-13b微调模型,生成高考......
  • CSS fit-content属性:弹性布局的利器
    ......
  • Linux基本指令:掌握日常操作的必备技能
    ......
  • 【C语言初阶】掌握C语言调试技巧,迈向高效编程的阶梯
    ......