数据结构顺序表(C语言实现)

这篇具有很好参考价值的文章主要介绍了数据结构顺序表(C语言实现)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

绪论

        从本章开始就是开始数据结构的开端,本章将会写出数据结构中的顺序表的代码实现,多会以注释的方法来描述一些细节(注释是我们程序员必须常用的工具)。

     数据结构顺序表(C语言实现)

 文章来源地址https://www.toymoban.com/news/detail-495682.html

话不多说安全带系好,发车啦(建议电脑观看)。


附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或者其余颜色为次重点;黑色为描述需要


目录

1.线性表

2.顺序表

2.1顺序表的结构:

2.1.1 顺序表的初始化:

2.1.2 顺序表的摧毁

2.1.3 顺序表的放入数据

2.1.4 顺序表的删除数据

2.1.5 打印顺序表的数据       

2.2顺序表的源代码:


1.线性表

知识点:

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串..

细节(注意点):

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组(地址连续)和链式结构(地址不连续)的形式存储。


2.顺序表

知识点:

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储(本质就是一个数组只不过用结构体包装了一下)。数据结构顺序表(C语言实现)

顺序表分为:静态顺序表(实现开辟好数组的空间大小)以及动态顺序表(用动态内存管理的方式来进行内存管理)

细节:

我们要实现一个顺序表的话首先我们要知道顺序表的框架:

  1. 顺序表的结构体
    1. 数组(a)
    2. 顺序表中的元素个数(size)
    3. 容量(用于动态顺序表,是动态申请的大小,用于和元素个数比较判断申请空间是否足够)
  2. 有了这个结构后,我们就需要实现一个顺序表的基本功能
    1. 将数据放进顺序表中
    2. 将顺序表中的数据删除
    3. 初始化顺序表(主要针对于动态开辟空间提前申请空间)
    4. 归还(摧毁)所借的空间
    5. 将顺序表中的数据打印出来

下面这要讲的是动态的顺序表、如果需要静态的将结构体中的容量去掉,再把数组改一下即可(若有问题的话可以评论我都会看),我们就把顺序表想成一个数组就能很好的理解了


2.1顺序表的结构:

顺序表所要的结构是由数组、元素个数、容量组成的

代码实现如下:

typedef struct SeqList//将结构体名称重命名为
{
	SLDataType* a;//开辟SLDataType(用typedef重定义类型名,这样方便与改变结构体内的数据类型)类型的空间
//数组的本质是指针所以为了更方便理解就直接写成指针的形式SLDataType* a 
	int size;//元素个数
	int capacity;//容量
}SeqList;//重命名为SeqList 这样方便后面使用
//宏定义如下:
//#define SLDataType int 
//使用结构体类型
//SeqList s;即可
//不用写成 struct SeqList s;

2.1.1 顺序表的初始化:

将容量capacity和个数size进行简单的初始化,主要是申请一片空间来给a来存数据

代码如下:

void InitSeqList(SeqList* obj)//将结构体用指针接收
{
	assert(obj);
	obj->capacity = INIT_CAPACITY;//通过指针来访问结构体中的成员,将capacity先初始化为INIT_CAPACITY(用宏来确定capacity的起始大小,这样方便后改变)
	obj->size = 0;//0个成员
	obj->a = (SLDataType*)malloc(sizeof(SLDataType) * obj->capacity);//malloc动态申请结构体大小的capacity个空间
	if (obj->a == NULL)//判断一下是否申请成功
	{
		perror("malloc");//如果失败就报错
		return;
	}
}

//宏
//#define INIT_CAPACITY 4 (这是应该定义在头文件中的)

//调用的方法
//SeqList s;(应该定义在测试test.c文件中)
//InitSeqList(&s);

//而一般的结构的实现又是放在SeqList.c的文件中,这样来进行分源管理

2.1.2 顺序表的摧毁

顺序表的摧毁主要是为了将向操作系统借的空间归还,以及再将容量和元素个数归为0

void DestorySeqList(SeqList* obj)//指针接收结构
{
	assert(obj);//判断结构是否为空,防止访问到NULL指针(这是一个好习惯)
	free(obj->a);//直接释放所借用的空间
	obj->a = NULL;//再将其置为NULL
	obj->capacity = obj->size = 0;//将容量和个都置为0,摧毁了自然就没了
}

//调用方法
//SeqList s;
//DestorySeqList(&s);

2.1.3 顺序表的放入数据

1.从尾部插入数据

尾部插入就比较的简单了,因为顺序表其实是一个数组所以直接在最后位置插入数据就行(此时最后位置的下标就是元素个数)。

 

void SeqListBackPush(SeqList* obj, SLDataType x)//将结构体用指针接收通过指针来找到成员,x是所要尾插的数据
{
	assert(obj);//判断结构体是否为NULL

	If_Add_Capacity(obj);//判断数据是否已经把所借的容量填满了

	obj->a[(obj->size)++] = x;//在a的最后位置插入数据,可以发现其实size个数就是最后位置的下标
}

但要注意判断容量是否满足,如果容量已经是满的了(size == capacity)就需要扩容,If_Add_Capacity (判断是否要增容)

void If_Add_Capacity(SeqList* obj)
{
	if (obj->size == obj->capacity)//判断已有成员个数是否等于容量,若等则进去
	{
		SLDataType* ptr = (SLDataType*)realloc(obj->a, sizeof(SLDataType) * obj->capacity * 2);//进来后就说明空间不够了,需要开空间
		//一般多直接开辟比容量大两倍的空间 即 对a开辟结构体大小为原capacity两倍的空间
		if (ptr == NULL)//判断是否申请成功
		{
			perror("realloc");//不成功则报错

			return;
		}
		obj->a = ptr;//因为可能是异地扩容所以还要将ptr赋值给数组a
		obj->capacity *= 2;//容量 乘于 2
		ptr = NULL;//无用的指针置为NULL(好习惯)
	}
}

2.从头部插入

在一个数组中若想从头部插入 你就需要把数据先全部往后挪动一位,再将这个数据存放到第一个位置处。

void SeqListFrontPush(SeqList* obj, SLDataType x)
{
	assert(obj);//判空

	If_Add_Capacity(obj);//判是否满了
	for (int i = obj->size; i > 0; i--)//将所有数据往后移一位
	{
		obj->a[i] = obj->a[i - 1];//此处只要是未满的就能直接就行移位并不会有事
	}
	obj->a[0] = x;//在a[0]位置处添加数据
	obj->size++;//元素个数++,这可别忘了!
}

3.指定位置插入

在满足pos位置是一个正常的位置的前提下,并且同样需要判断是否要扩容, 要在某个位置处插入,其本质其实和头插有些类似,需要把插的位置后的数据全部往后挪一位后,最后再在那个位置插入数据即可。


void SeqListInsert(SeqList* obj, int pos, SLDataType x)//在pos位置处添加数据
{
	assert(obj);//判空
	pos -= 1;//换成下标
	assert(pos >= 0 && pos <= obj->size);//判断这个位置是否有问题
	If_Add_Capacity(obj);//判断是否满了
	int i = obj->size;//和头插的方法几乎一样
	for (i; i > pos; i--)//将从位置处开始的数据全部往后挪一位
	{
		obj->a[i] = obj->a[i - 1];//从尾部开始防止覆盖
	}
	obj->a[i] = x;//在位置处插入数据
	obj->size++;//size++ 别忘了!
}

2.1.4 顺序表的删除数据

1. 从尾部删除

在删除之前我们需要判断一下是否还有数据在顺序表中(assert(obj->size > 0)),对于一个数组来说我们删除时直接对元素个数进行 - - 即可并不会去真正的删除,当下一次插入数据时就直接覆盖了,也不会有什么影响。

void SeqListBackPop(SeqList* obj)
{
	assert(obj);//判空
	assert(obj->size > 0);//为真就过、为假就会报错,若没有数据那就是有问题的

	obj->size--;//此处的尾删并不直接将空间归还,而仅仅只是把元素个数-1这样

	//就不会访问到,即使后面需要再次添加数据也就直接覆盖了,因为要归还空间的成本太高了
}

2.从头部删除

同样我们需要先判断一下顺序表中是否还有数据、对于头部删除来说直接将第一个数据覆盖了就好 。

void SeqListFrontPop(SeqList* obj)
{
	assert(obj);//判空
	assert(obj->size > 0);//判断是否有数据
	for (int i = 0; i < obj->size - 1; i++)//直接从第2个位置开始往前覆盖掉即可
	{
		obj->a[i] = obj->a[i + 1];
	}
	obj->size--;//注意要 - - 
}

3.指定位置删除

判断pos是否在顺序表中、最后将从pos+1位置开始数据覆盖即可。

void SeqListErase(SeqList* obj, int pos)
{
	assert(obj);//判空
	assert(obj->size > 0);//是否有数据

	pos -= 1;//换成下标
	assert(pos >= 0 && pos <= obj->size);//是否符合要求

	for (int i = pos; i < obj->size - 1; i++)//和头删对应此处就应该是从pos+1位置处开始往前覆盖
	{
		obj->a[i] = obj->a[i + 1];//将pos位置处先覆盖 , 然后以此往后
	}
	obj->size--;//注意 - -
}

2.1.5 打印顺序表的数据       

就和数组的打印一样,直接遍历打印即可

void SeqListPirnt(SeqList* obj)//指针接收结构体
{
	assert(obj);//判空
	for (int i = 0; i < obj->size; i++)//从下标为0的位置处开始往后遍历
	{
		printf("%d ", obj->a[i]);//结构体访问成员:*obj表示结构体 在 .访问 就还能写成 (*obj).a[i] 这两个是等价的一般喜欢用前面方法
	}
	printf("\n");//换行
}

如果有任何问题,欢迎讨论!


2.2顺序表的源代码:

我将全部放在一个里面对于分源内容请自行分开,或者直接合并也行(合并方法将声明以及包含自身的头文件去掉即可直接使用)

//SeqList.h
#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>


#define INIT_CAPACITY 4
//sequence

typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* a;
	int size;
	int capacity;
}SeqList;

void InitSeqList(SeqList * obj);
void DestorySeqList(SeqList* obj);

void SeqListBackPush(SeqList* obj,SLDataType x );

void SeqListBackPop(SeqList* obj);

void SeqListPirnt(SeqList* obj);

void SeqListFrontPush(SeqList* obj, SLDataType x);

void SeqListFrontPop(SeqList* obj);

void SeqListInsert(SeqList* obj, int pos, SLDataType x);

void SeqListErase(SeqList* obj, int pos);

//SeqList.c

 #define _CRT_SECURE_NO_WARNINGS 1

#include"SeqLIst.h"
//sequence 顺序

void If_Add_Capacity(SeqList* obj)
{
	if (obj->size == obj->capacity)
	{
		SLDataType* ptr = (SLDataType*)realloc(obj->a, sizeof(SLDataType) * obj->capacity * 2);
		if (ptr == NULL)
		{
			perror("realloc");

			return;
		}
		obj->a = ptr;
		obj->capacity *= 2;
		ptr = NULL;
	}
	return;
}

void InitSeqList(SeqList* obj)
{
	assert(obj);

	obj->capacity = INIT_CAPACITY;
	obj->size = 0;
	obj->a = (SLDataType*)malloc(sizeof(SLDataType) * obj->capacity);
	if (obj->a == NULL)
	{
		perror("malloc");
		return;
	}
}

void DestorySeqList(SeqList* obj)
{
	assert(obj);

	free(obj->a);
	obj->a = NULL;
	obj->capacity = obj->size = 0;
}

void SeqListBackPush(SeqList* obj, SLDataType x)
{
	assert(obj);
	
	If_Add_Capacity(obj);

	obj->a[(obj->size)++] = x;

}

void SeqListBackPop(SeqList* obj)
{
	assert(obj);
	assert(obj->size > 0);//为真就过、为假就会报错
	
	obj->size--;
}

void SeqListPirnt(SeqList* obj) 
{
	assert(obj);
	for (int i = 0; i < obj->size; i++)
	{
		printf("%d ", obj->a[i]);
	}
	printf("\n");
}


void SeqListFrontPush(SeqList* obj, SLDataType x)
{
	assert(obj);

	If_Add_Capacity(obj);
	for (int i = obj->size; i > 0; i--)
	{
		obj->a[i] = obj->a[i - 1];
	}
	obj->a[0] = x;
	obj->size++;
}

void SeqListFrontPop(SeqList* obj)
{
	assert(obj);
	assert(obj->size > 0);
	for (int i = 0; i < obj->size - 1; i++)
	{
		obj->a[i] = obj->a[i + 1];
	}
	obj->size--;
}

void SeqListInsert(SeqList* obj, int pos, SLDataType x)
{
	assert(obj);
	pos -= 1;//换成下标
	assert(pos >= 0 && pos <= obj->size);
	If_Add_Capacity(obj);
	int i = obj->size;
	for (i; i > pos; i--)//从最后开始将填充数据
	{
		obj->a[i] = obj->a[i - 1];
	}
	obj->a[i] = x;
	obj->size++;
}

void SeqListErase(SeqList* obj, int pos)
{
	assert(obj);
	assert(obj->size > 0);

	pos -= 1;//换成下标
	assert(pos >= 0 && pos <= obj->size);

	for (int i = pos; i < obj->size - 1; i++)
	{
		obj->a[i] = obj->a[i + 1];
	}
	obj->size--;

}

//test.c
//测试是否能用

 #define _CRT_SECURE_NO_WARNINGS 1

#include"SeqLIst.h"

int main()
{
	SeqList s;
	InitSeqList(&s);
	SeqListPush(&s, 1);
	SeqListPush(&s, 2);
	SeqListPush(&s, 3);
	SeqListPush(&s, 4);
	SeqListPush(&s, 5);

	SeqListPop(&s);
	SeqListPop(&s);
	SeqListPop(&s);

	SeqListFrontPush(&s, 0);

	SeqListFrontPush(&s, -1);

	SeqListInsert(&s, 1, 3);
	SeqListErase(&s, 2);
	SeqListPirnt(&s);

	DestorySeqList(&s);

	return 0;
}

分源管理时的头文件 :

数据结构顺序表(C语言实现)

 

 

持续更新大量数据结构细致内容,三连关注哈

 

 

 

到了这里,关于数据结构顺序表(C语言实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言数据结构】模拟·顺序表·总项目实现

    💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃 个人主页 :阿然成长日记 👈点击可跳转 📆 个人专栏: 🔹数据结构与算法🔹C语言进阶 🚩 不能则学,不知则问,耻于问人,决无长进 🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍 我在上一篇博客中,

    2024年02月15日
    浏览(31)
  • 【数据结构初阶】二、 线性表里的顺序表(C语言实现顺序表)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【数据结构初阶】一. 复杂度讲解_高高的胖子的博客-CSDN博客  =======================================

    2024年02月08日
    浏览(30)
  • 【数据结构】线性表的顺序存储结构及实现——C语言版

    线性表的顺序存储结构称为 顺序表 ,其基本思想是 用一段地址连续的存储单元一次存储线性表的数据元素。 设顺序表的每个元素占用 c 个存储单元,则第 i 个元素的存储地址为: 所以, 只要确定了存储顺序表的起始地址(即基地址),计算任意一个元素的存储地址的时间

    2024年03月15日
    浏览(40)
  • 数据结构之顺序表的实现(C语言版)

         Hello, 大家好,我是一代,今天给大家带来有关顺序表的有关知识      所属专栏:数据结构      创作不易,望得到各位佬们的互三呦 1.首先在讲顺序表之前我们先来了解什么是数据结构 数据结构是由“数据”和“结构”两词组合⽽来。 什么是数据?常见的数值1、

    2024年04月25日
    浏览(36)
  • 【数据结构】链表OJ题(顺序表)(C语言实现)

    ✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ 🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿 🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟 🌟🌟 追风赶月莫停留 🌟🌟 🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀 🌟🌟 平芜尽处是春山

    2024年02月05日
    浏览(37)
  • 【数据结构】C语言实现顺序栈(附完整运行代码)

    🦄 个人主页 :修修修也 🎏 所属专栏 :数据结构 ⚙️ 操作环境 : Visual Studio 2022 在本次项目中我们的目标是 实现一个 顺序栈 : 该 顺序栈 使用 动态内存分配空间 ,可以用来 存储任意数量的同类型数据 . 顺序栈 结构体 需要包含 三个要素 : 存放数据的数组arr,栈顶元素下标top

    2024年04月29日
    浏览(24)
  • 数据结构初阶之顺序表(C语言实现)

    顺序表是数据结构里面很基础的一类,它是线性表的一种,其它线性表还有链表、栈和队列等,今天来和博主一起学习关于顺序表的知识吧。 顺序表,它分为两类: 动态顺序表 和 静态顺序表 ,这两个表的区别就是 前者的空间不固定 ,是 支持扩容 的,后者的 空间是固定

    2024年02月03日
    浏览(34)
  • 【数据结构】详谈队列的顺序存储及C语言实现

    大家好,很高兴又和大家见面啦!!! 在上一篇内容中,我们在介绍完队列的基本概念、重要术语以及基本操作后,又回顾了一下数据结构的三要素——数据的逻辑结构、数据的存储结构以及数据的运算。 队列这种数据结构我们已经介绍了它的逻辑结构以及数据运算的定义

    2024年01月21日
    浏览(63)
  • 【数据结构】顺序表基本操作的实现(C语言)

    🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。 🐌 个人主页:蜗牛牛啊 🔥 系列专栏:🛹数据结构、🛴C++ 📕 学习格言:博观而约取,厚积而薄发 🌹 欢迎进来的小伙伴,如果小伙伴们在学习的过程中,发现有需要纠正的地方,烦请指正,希望能够与

    2024年02月16日
    浏览(43)
  • C语言数据结构-----顺序表(多功能动态顺序表的代码实现)

    本篇讲述了顺序表的相关知识,以及动态顺序表的代码实现。 顺序表和链表一般情况下都会叫他们线性表。 线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串… 线性

    2024年02月07日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包