数据结构——顺序表

目录

前言

一、顺序表的定义和特点

二、顺序表分类

三、基本操作

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

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

有误之处望指正!!

相关推荐
A懿轩A1 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
古希腊掌管学习的神1 小时前
[搜广推]王树森推荐系统——矩阵补充&最近邻查找
python·算法·机器学习·矩阵
云边有个稻草人1 小时前
【优选算法】—复写零(双指针算法)
笔记·算法·双指针算法
半盏茶香1 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
忘梓.2 小时前
解锁动态规划的奥秘:从零到精通的创新思维解析(3)
算法·动态规划
️南城丶北离2 小时前
[数据结构]图——C++描述
数据结构··最小生成树·最短路径·aov网络·aoe网络
✿ ༺ ོIT技术༻2 小时前
C++11:新特性&右值引用&移动语义
linux·数据结构·c++
字节高级特工2 小时前
【C++】深入剖析默认成员函数3:拷贝构造函数
c语言·c++
计算机学长大白3 小时前
C中设计不允许继承的类的实现方法是什么?
c语言·开发语言
tinker在coding4 小时前
Coding Caprice - Linked-List 1
算法·leetcode