数据结构——顺序表

目录

前言

一、顺序表的定义和特点

二、顺序表分类

三、基本操作

1、静态顺序表

2、动态顺序表

四、总结



前言

顺序表是数据结构中的一种重要形式,它属于线性表的一种顺序存储结构,其逻辑上相邻的元素在物理存储位置上也相邻。

其中使用到C语言内存管理的内容,可以先查阅:C语言------内存管理_c语言内存管理文章浏览阅读1k次,点赞32次,收藏22次。C语言中,内存管理需要对静态和动态内存分配,静态分配在编译时确定,而动态分配(如malloc, calloc, realloc)则在运行时进行,需程手动管理,包括适时释放(用free)以避免内存泄漏。同时,了解栈、堆、数据区、代码区等内存区域的特性和用途,对于有效管理内存至关重要。_c语言内存管理https://blog.csdn.net/qq_67319052/article/details/140631403


一、顺序表的定义和特点

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。

顺序表具有以下特点:顺序表可以根据需要动态地增加或减少存储空间,以适应不同数量的数据元素;顺序表中逻辑上相邻的元素在物理存储位置上也相邻;由于顺序表在物理上是连续存储的,因此可以通过索引直接访问任何位置的元素。

二、顺序表分类

静态顺序表 :使用定长数组存储元素。静态顺序表的存储空间在编译时就已确定,无法在运行时改变。因此,它适用于存储数量固定且已知的数据元素。静态顺序表的缺陷在于存储空间固定,扩展性差,灵活性不足。

cpp 复制代码
typedef int data_t;
#define N 128    // 数组大小已定
struct sqlist_t {
	data_t data[N];
	int last;
};
typedef struct sqlist_t sqlist;
typedef struct sqlist_t * sqlink;
//与下面写法等价
/*
typedef int data_t;
#define N 128 

typedef struct {
	data_t data[N];
	int last;
}sqlist, *sqlink;
*/

动态顺序表 :使用动态开辟的数组来存储数据元素。动态顺序表允许在运行时根据需要自动调整存储空间的大小,以适应不同数量的数据元素。这种数据结构在实际应用中非常有价值,因为它既保持了顺序表随机访问的高效性,又克服了静态顺序表存储空间固定、扩展性差的缺点。

cpp 复制代码
typedef int data_t;

typedef struct {  
    data_t *data;       // 指向动态分配的数组的指针  
    int len;            // 数组长度  
    int last;             
} sqlist,* sqlink;

三、基本操作

1、静态顺序表

创建顺序表

对于静态顺序表而言,其相当于一个已知的数组,其长度大小固定。

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int data_t;
#define N 128    // 数组大小已定

typedef struct {
	data_t data[N];
	int last;
}sqlist, *sqlink;

sqlink list_create() //创建顺序表,返回顺序表地址
{
	sqlink L;
	L =(sqlink)malloc(sizeof(sqlist));
	if (L == NULL) 
    {
		printf("list malloc failed\n");
		return L;
	}
	memset(L, 0, sizeof(sqlist));//将顺序表中成员的初始值都设置为0
	L->last = -1;//数组索引,开始时设为1
	return L;//返回顺序表指针
}

顺序表插入与删除

创建完完成之后,就可以对顺序表插入数据了,需要参数为:插入的数据,以及插入的位置。

cpp 复制代码
int list_insert(sqlink L, data_t value, int pos) 
{
	int i;
	//判断顺序表是否满了
	if (L->last == N-1) 
    {
		printf("list is full\n");
		return -1;
	}
	//判断位置是否合理
	if (pos < 0 || pos > L->last+1) 
    {
		printf("Pos is invalid\n");
		return -1;
	}
	//移动数据,留出插入数据的位置
	for (i = L->last; i >= pos; i--) L->data[i+1] = L->data[i];
	//插入数据,并更新数据长度
	L->data[pos] = value;
	L->last++;
	return 0;
}

删除指定位置的数据也是同理,需要只需要将指定位置的后面的数据依次往前移动一个单元即可,然后把尾部索减一。

cpp 复制代码
int list_delete(sqlink L, int pos) 
{
	int i;
	if (L->last == -1) 
    {
		printf("list is empty\n");
		return -1;
	}
	if (pos < 0 || pos > L->last) 
    {
		printf("delete pos is invalid\n");
		return -1;
	}
	for (i = pos+1; i <= L->last; i++) L->data[i-1] = L->data[i];
	L->last--;
	return 0;
}

顺序表释放

在使用完顺序表之后,需要将其内存释放,因为这里是使用动态内存分配的空间。

cpp 复制代码
int list_free(sqlink L)
{
	if (L == NULL) 
		return -1;
	free(L);
	L = NULL;
	return 0;
}

其他操作

如顺序表的清除,检验是否为空,当前数据的长度,打印显示,数据查找并返回索引等操作。

cpp 复制代码
int list_clear(sqlink L) //清除顺序表
{
	if (L == NULL)
		return -1;
	memset(L, 0, sizeof(sqlist));
	L->last = -1;
	return 0;
}

int list_empty(sqlink L) //判断顺序表是否为空
{
	if (L->last == -1) 
		return 1;
	else 
		return 0;
}

int list_length(sqlink L) //返回顺序表长度
{
	if (L == NULL) 
		return -1;
	return (L->last+1);
}

int list_show(sqlink L) //顺序表遍历打印
{
	int i;
	if (L == NULL) 
		return -1;
	if (L->last == -1)
		printf("list is empty\n");
	for (i = 0; i <= L->last; i++)
    {
		printf("%d ", L->data[i]);
	}
	puts("\n");
	return 0;
}
int list_locate(sqlink L, data_t value) //数据查找,并返回位置
{
	int i ;
	for (i = 0; i <= L->last; i++) 
    {
		if (L->data[i] == value) 
			return i;
	}
	return -1;
}

2、动态顺序表

创建顺序表

与静态顺序表不同,动态顺序表不依赖于固定大小的数组,而是使用动态内存分配(如C语言中的malloc函数)来管理存储空间。

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int data_t;
typedef struct {  
    data_t *data;       // 指向动态分配的数组的指针  
    int len;            // 数组长度  
    int last;             
} sqlist,* sqlink;

sqlink sqlist_create(int len) //创建长度为len的顺序表
{
	sqlink L;
	if ((L =(sqlink)malloc(sizeof(sqlist))) == NULL) //动态分配顺序表结构体的内存
    {
		printf("malloc sqlist failed\n");
		return NULL;
	}
	if ((L->data = (data_t *)malloc(len * sizeof(data_t)))==NULL) //动态分配结构体中数组的大小
    {
		printf("malloc data failed\n");
		free(L);//数据内存分配失败时,最好将前面分配的结构体内存给释放掉
		return NULL;
	}
	memset(L->data, 0, len*sizeof(data_t));//初始化数组
	L->len = len;//初始化长度
	L->last= -1;
	return L;
}

其他操作

相较于静态顺序表,动态顺序表只是自定义了存储数据空间的大小,将原来已知的固定的N改为可变的len成员,其他与静态顺序表无异,所以动态顺序表的插入、删除、清空、打印等操作与静态顺序表相同,不再举例展示。区别于静态顺序表,这里使用了两次malloc进行动态内存分配,在顺序表内存时,需要进行两次free来释放,即malloc要与free配对使用。


四、总结

**1、空间利用率:**静态顺序表的空间利用率可能较低,因为无法在运行时调整存储空间的大小。而动态顺序表虽然可以动态调整存储空间的大小,但在扩容时可能会产生一定的空间浪费。

**2、元素类型:**顺序表可以存储任意类型的元素,包括基本数据类型和结构体等。但是,在使用时需要注意元素类型的一致性,以便正确地访问和修改元素的值。

顺序表的使用和操作有很多,本文只是做个简介。

有误之处望指正!!

相关推荐
Komorebi.py8 分钟前
【Linux】-学习笔记05
linux·笔记·学习
不去幼儿园11 分钟前
【MARL】深入理解多智能体近端策略优化(MAPPO)算法与调参
人工智能·python·算法·机器学习·强化学习
Mr_Xuhhh13 分钟前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
亦枫Leonlew17 分钟前
微积分复习笔记 Calculus Volume 1 - 6.5 Physical Applications
笔记·数学·微积分
盼海1 小时前
排序算法(五)--归并排序
数据结构·算法·排序算法
网易独家音乐人Mike Zhou5 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
冰帝海岸5 小时前
01-spring security认证笔记
java·笔记·spring
小二·6 小时前
java基础面试题笔记(基础篇)
java·笔记·python
搬砖的小码农_Sky7 小时前
C语言:数组
c语言·数据结构
Swift社区8 小时前
LeetCode - #139 单词拆分
算法·leetcode·职场和发展