数据结构中的顺序表的实现

news2024/11/25 6:37:33

文章目录

  • 前言
  • 一、初识数据结构
  • 二、顺序表的实现(类型一)
    • 1.顺序表的头文件
    • 2.顺序表的实现
  • 三、顺序表的实现(类型二)
    • 1 顺序表头文件
    • 2 顺序表的实现
  • 四、线性表(顺序表)的缺点
  • 总结


前言


本期就进入到我们数据结构模块的分享了,数据结构其实是一门凌驾于各种语言上层的一门学科,所以数据结构完全可以脱离语言来学习,但不得不说的是各种语言确实赋予了数据结构新的各种实体实现形式,因此数据结构是我们灵活使用各种语言的一种手段,它们之间相辅相成;数据结构提高了语言处理业务的效率,语言使得数据结构灵活应用于各类开发;

一、初识数据结构

程序其实是数据结构和算法的总和;
数据结构:程序操作的数据对象的结构特性;
数据结构中我们需要掌握的主要内容有以下几个:
在这里插入图片描述
在学习每个模块之前必须把大体章程做到心中有数,这个也是我们为学习数据结构为自己建造的新的数据结构,哈哈哈;总之,就是讲求效率;

二、顺序表的实现(类型一)

这里必须强调一下:学习数据结构一定必须注意数据结构体的设置定义,一个好的数据结构体的定义,往往能够极大的提高书写数据结构以及使用数据结构;

1.顺序表的头文件

首先来看一下顺序表中的结构体的定义:
本结构体定义的优点是能够直接得到当前存放元素的个数以及顺序表的总长度;

#ifndef __SEQLIST_H__
#define __SEQLIST_H__

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

/* 存储数据对象类型 */
typedef int DataType;

/* 顺序表表头类型 */
typedef struct list
{
	DataType *pData;		//存储对象的空间首地址
	int tlen;				//最多存放元素的个数
	int clen;				//当前存放元素的个数
}SeqList;

extern SeqList *CreatSeqList(int MaxLen);		
extern int IsFullSeqList(SeqList *pTmpList);
extern int IsEmptySeqList(SeqList *pTmpList);
extern int InsertTailList(SeqList *pTmpList, DataType TmpData);
extern int ShowSeqList(SeqList *pTmpList);
extern int InsertPosData(SeqList *pTmpList, DataType TmpData, int Pos);
extern int DeleteSeqList(SeqList *pTmpList, int ptmp);
extern int UpdateSeqList(SeqList *pTmpList, DataType OldData, DataType NewData);
extern DataType *SearchSeqList(SeqList *pTmpList, DataType TmpData);
extern int ClearSeqList(SeqList *pTmpList);
extern int DestroySeqList(SeqList **pTmpList);

#endif

2.顺序表的实现

每个函数的功能均有标注,代码如下:

#include "Seqlist.h"

/* 创建一个顺序表 */
SeqList *CreatSeqList(int MaxLen)
{
	SeqList *pTmpList = NULL;

	pTmpList = malloc(sizeof(SeqList));	//为表头创建空间
	if (NULL == pTmpList)
	{
		perror("fail to pTmpList");
		return NULL;
	}

	pTmpList->tlen = MaxLen;
	pTmpList->clen = 0;
	pTmpList->pData = malloc(sizeof(DataType) * MaxLen);	//创建顺序表的数据存储空间
	if (NULL == pTmpList->pData)
	{
		perror("fail to malloc");
		return NULL;
	}

	return pTmpList;
}
/* 判断顺序表是否为满 */
int IsFullSeqList(SeqList *pTmpList)
{
	return pTmpList->tlen == pTmpList->clen ? 1 : 0;
}

/* 判断顺序表是否为空 */
int IsEmptySeqList(SeqList *pTmpList)
{
	return pTmpList->tlen == 0 ? 1 : 0;
}
/* 在表中插入一个数据 */
int InsertTailList(SeqList *pTmpList, DataType TmpData)
{
	if (IsFullSeqList(pTmpList))
	{
		return -1;
	}

	pTmpList->pData[pTmpList->clen] = TmpData;
	pTmpList->clen++;

	return 0;
}
/* 打印列表中的所有元素 */
int ShowSeqList(SeqList *pTmpList)
{
	int i = 0;
	for (i = 0;i < pTmpList->clen;++i)
	{
		printf("%d ", pTmpList->pData[i]);
	}
	putchar('\n');
	return 0;
}
/* 按照位置插入数据 */
int InsertPosData(SeqList *pTmpList, DataType TmpData, int Pos)
{
	int i = 0;

	if (IsFullSeqList(pTmpList) || (Pos < 0) || Pos > pTmpList->clen)
	{
		return -1;
	}
	
	for (i = pTmpList->clen;i > Pos;--i)
	{
		pTmpList->pData[i] = pTmpList->pData[i - 1];
	}
	
	pTmpList->pData[i] = TmpData;
	++pTmpList->clen;
	return 0;
}
/* 删除元素(只删除第一个),多次删除循环调用即可 */
int DeleteSeqList(SeqList *pTmpList, int ptmp)
{
	int i = 0;
	int j = 0;

	if ( IsEmptySeqList(pTmpList))
	{
		return -1;
	}

	for (j = 0;j < pTmpList->clen; j++)
	{
		if (pTmpList->pData[j] == ptmp)
		{
			for (i = j;i < pTmpList->clen - 1;++i)
			{
				pTmpList->pData[i] = pTmpList->pData[i + 1];
			}
			pTmpList->clen--;
			break;					//i--为删除所有的元素
		}
	}
	return 0;
}
/* 修改元素 */
int UpdateSeqList(SeqList *pTmpList, DataType OldData, DataType NewData)
{
	int i = 0;

	for (i = 0;i < pTmpList->clen; ++i)
	{
		if (pTmpList->pData[i] == OldData)
		{
			pTmpList->pData[i] = NewData;
		}
	}

	return 0;
}
/* 查找元素 */
DataType *SearchSeqList(SeqList *pTmpList, DataType TmpData)
{
//	int a[pTmpList->clen] = {0};
	int i = 0;
//	int j = 0;

	for (i = 0;i < pTmpList->clen;++i)
	{
		if (pTmpList->pData[i] == TmpData)
		{
			return &pTmpList->pData[i];
		}
	}
	return NULL;
}

/* 清零顺序表 */
int ClearSeqList(SeqList *pTmpList)
{
	pTmpList->clen = 0;
	return 0;
}
/* 销毁顺序表 */
int DestroySeqList(SeqList **pTmpList)
{
	free((*pTmpList)->pData);
	free(*pTmpList);
	*pTmpList = NULL;
	return 0;
}

三、顺序表的实现(类型二)

1 顺序表头文件

相比于上一种的类型定义形式,那么这个的缺点是必须手动宏定义顺序表的总长度,并且结构体只有存放顺序表最后一个元素个数(顺序表中元素总个数)的数据;其实两者从本质上来讲都是一样的,都是使用数组开辟一段连续的空间地址进行顺序存储;
头文件内容如下:

#ifndef __SQLIST_H__
#define __SQLIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int data_t;

#define N	128

typedef struct sqlist_t {
	
	data_t data[N];
	int last;						//顺序表中实际最后一个元素的下标

}sqlist, *sqlink;

/*
 * 与上面的自定义结构体等价
typedef struct sqlist_t sqlist;		//自定义结构体
typedef struct sqlist_t *sqlink;	//自定义指针
*/

/* 创建一个顺序表(返回值为链表指针类型) */
extern sqlink list_create(void);

/* 清零线性表(只清零不释放空间) */
extern int list_clear(sqlink L);

/* 删除线性表(释放空间) */
extern int list_delete(sqlink L);

/* 判断线性表是否为空 */
extern int list_empty(sqlink L);

/* 获取线性表的长度 */
extern int list_length(sqlink L);

/* 得到val在线性表中的位置 */
extern int list_locate(sqlink L, data_t val);

/* 在线性表的pos处插入一个数据 */
extern int list_insert(sqlink L, data_t val, int pos);

/* 列出线性表中的所有元素 */
extern int list_show(sqlink L);

/* 将两个线性表进行合并(取并集) */
extern int list_merge(sqlink L1, sqlink L2);

/* 消除线性表中所有重复的元素 */
extern int list_purge(sqlink L);

/* 删除线性表中pos处的成员 */
extern int list_DeleteMember(sqlink L, int pos);

#endif

2 顺序表的实现

那么具体来看下如何实现:

#include "sqlist.h"

sqlink list_create(void)
{
	sqlink L;
	int i = 0;

	L = (sqlink)malloc(sizeof(sqlist));	//为线性表申请空间
	if (NULL == L)
	{
		perror("fail to malloc");
		return L;
	}

	memset(L, 0, sizeof(sqlist));		//清零线性表空间

	L->last = -1;						//将最后一个位置先置为-1

	return L;							//返回线性表地址
}

int list_clear(sqlink L)
{
	if (L == NULL)
	{
		return -1;
	}

	memset(L, 0, sizeof(sqlist));		//清零线性表空间

	L->last = -1;						//将最后一个位置先置为-1

	return 0;
}

int list_delete(sqlink L)
{
	if (NULL == L)
		return -1;

	free(L);
	L = NULL;
	return 0;
}

int list_empty(sqlink L)
{
	if (L->last == -1)
	{
		return 1;
	}

	return 0;
}

int list_length(sqlink L)
{
	if (L == NULL)
	{
		return -1;
	}
	return L->last + 1;
}

int list_locate(sqlink L, data_t val)
{
	int i = 0;

	for(i = 0; i <= L->last; ++i)
	{
		if (L->data[i] == val)
		{
			return i;
		}
	}

	return -1;
}

int list_insert(sqlink L, data_t val, int pos)
{
	int i = 0;

	if (N - 1 == L->last)				//判断线性表是否为满
	{
		printf("线性表满!\n");
		return 0;
	}

	if (pos < 0 || pos > L->last + 1)		//判断位置是否有效(此处按原理来讲pos > L->last表示可以在最后一个位置插入)
	{
		printf("插入位置无效!\n");
		return -1;
	}
	
	for (i = L->last; i >= pos; --i)	//将pos和pos之后的元素向后平移一个位置
	{
		L->data[i + 1] = L->data[i];
	}

	L->data[pos] = val;					//插入元素

	L->last += 1;						//最后下标+1

	return 0;
}

int list_show(sqlink L)
{
	int i = 0;


	if (L == NULL)
	{
		return -1;
	}
	if (-1 == L->last)
	{
		printf("线性表是空的!\n");
	}

	for (i = 0; i <= L->last; ++i)
	{
		printf("%d ", L->data[i]);
	}
	putchar('\n');

	return 0;
}

int list_DeleteMember(sqlink L, int pos)
{
	int i = 0;

	if (list_empty(L))
	{
		printf("线性表是空的!\n");
		return -1;
	}
	if (pos < 0 || pos > L->last)		//判断位置是否有效
	{
		printf("删除位置无效!\n");
		return -1;
	}

	for (i = pos; i < L->last; ++i)			//每个元素向前移动
	{
		L->data[i] = L->data[i + 1];
	}

	L->last--;

	return 0;
}

int list_merge(sqlink L1, sqlink L2)
{
	int i = 0;
	int j = 0;
	
	if (list_empty(L2))
	{
		printf("线性表是空的\n");
		return -1;
	}

	for(i = 0; i <= L2->last; ++i)
	{
		for(j = 0; j <= L1->last; ++j)
		{
			if (L1->data[i] == L2->data[j])
			{
				break;
			}
		}

		if (j == L1->last + 1)
		{
			L1->data[L1->last + 1] = L2->data[i];
			L1->last++;
		}
	}

	return 0;
}

int list_purge(sqlink L)
{
	int i = 0;
	int j = 0;

	if (list_empty(L))
	{
		printf("线性表是空的\n");
		return -1;
	}

	if (L->last == 0)
	{
		return 0;
	}

	while (i < L->last)
	{
		j = i + 1;
		while (j <= L->last)
		{
			if (L->data[i] == L->data[j])
			{
				list_DeleteMember(L, j);		//删除数据后j不需要+1
			}
			else 
			{
				j++;							//只有当没有删除的时候j需要+1
			}
		}
		i++;
	}

	return 0;
}

四、线性表(顺序表)的缺点

	线性表的顺序存储结构有存储密度高及能够随机存取等优点,
	但存在以下不足:
		(1)要求系统提供.-片较大的连续存储空间。	
		(2)插入、删除等运算耗时,.且存在元素在存储器中成片移动的现象;

总结

本期主要分享了数据结构的总体章程以及数据结构中顺序表的实现过程,那么给出了顺序存储的两种形式(定义结构体不同),当然,萝卜白菜各有所爱,我比较喜欢第一种,操作起来比较方便,因为它在结构体中直接存储了顺序表的总个数,显得整个顺序表具有整体性;但是两种形式在本质上气势上是一样的,都是顺序表且本质完全一致;小伙伴们学起来,加油!
最后,各位小伙伴们如果喜欢我的分享可以点赞收藏哦,你们的认可是我创作的动力,一起加油!

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

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

相关文章

[前端语法]js原型链有关的继承问题

深夜反而思维更活跃一些 (1)js中的原型链 js中存在一个名为原型链的机制,其特点如下 加入一个方法A,A方法一个属性为prototype,这个属性会指向某个对象,也成为A类对象的原型对象. 当我们根据A这个方法生成一个对象a,那么a的原型(proto)属性即为这个对象 a可以调用一些原型…

【cropperjs】优秀、优雅的前端图片裁剪库

下载 npm i cropperjsnpm官网- https://www.npmjs.com/package/cropperjs cropperjs关键参数 aspectRatio 图片裁剪比例 默认值 &#xff1a;NaN作用&#xff1a;图片裁剪比例值&#xff1a;自定义裁剪比例&#xff0c;例如1 / 1 , 4 / 3 , 16 / 9等 viewMode 裁剪模式 默认…

代码随想录算法训练营第二十七天| 39. 组合总和、 40.组合总和II、 131.分割回文串

组合总数 题目链接&#xff1a;力扣 这题和之前题目的区别在于&#xff0c;本题没有数量要求&#xff0c;可以无限重复的取某一元素&#xff0c;但是对元素的总和有限制&#xff0c;这就说明了递归的限制不在于层数&#xff0c;而是选取元素的总和超过target就返回 终止条件为…

【owt】WebrtcNode, subscirbe-sdp offer 流程(2)

流程图 创建MediaStream&#xff0c; MediaStream一方面作为从VideoFramePacketizer接收到媒体数据&#xff1b; 创建VideoFramePacketizer&#xff0c;MediaStream 把sink 注册到VideoFramePacketizer&#xff0c;这样VideoFramePacketizer&#xff08;继承了MediaSource&…

upload靶场通关(12-21关)

Pass-12&#xff08;白名单校验&#xff08;GET 型 0x00 截断&#xff09;&#xff09; 先看提示&#xff1a; 一头雾水&#xff0c;只知道了上传路径是可控的 查看源码&#xff1a; 能看懂就看看&#xff0c;反正我是看了同学的笔记得知这是白名单&#xff0c;按照文件名进行…

Customizable constraint systems for succinct arguments学习笔记(1)

1. 引言 微软研究中心Srinath Setty、a16z crypto research 和 Georgetown University Justin Thaler、Carnegie Mellon University Riad Wahby 20203年论文《Customizable constraint systems for succinct arguments》。 在该论文中&#xff0c;介绍了Customizable constra…

CMake学习(1): CMake基本使用

https://subingwen.cn/cmake/CMake-primer/ 1. CMake 概述 CMake是一个项目构建工具&#xff0c;并且是跨平台的。Cmake跟Makefile其实是差不多的&#xff0c;只不过makefile更底层些。大多是 IDE 软件都集成了 make&#xff0c;比如&#xff1a;VS 的 nmake、linux 下的 GNU…

单链表OJ题:LeetCode--141.环形链表

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下LeetCode中的第141道单链表OJ题&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; 数据结构与算法专栏&#xff1a;数据结构与算法 个 …

龙岗区五联土地整备利益统筹项目,集体物业集中签约仪式

五联土地整备利益统筹项目启动以来街道高度重视相关工作开专题会、建工作组、设党支部把征拆工作一项项推进 截至6月1日已完成&#xff1a; 清租签约73户&#xff0c;面积9.55万m&#xff08;意向签约17户&#xff0c;约1.66万m&#xff09; 私人住宅业主补偿安置签约8户&…

Java语言----反射、枚举以及lambda表达式

目录 一.反射 1.1反射的基本情况 1.2反射中最重要的类 1.2.1 Class类 1.2.2Field类 1.2.3Constructor类 1.2.4Methood类 1.3反射优缺点 二.枚举 2.1概念 2.2枚举&#xff08;enum&#xff09;类方法 2.3枚举的构造 三.Lambda表达式 3.1Lambda介绍 3.2 函数式接…

AI实战营:深度学习预训练与MMPreTrain

目录 一、MMPretrain算法库介绍 二、经典主干网络 残差网络ResNet&#xff08;2015&#xff09; Vision Transformer(2020) 三、自监督学习 四、多模态算法 一、MMPretrain算法库介绍 算法库与任务组成&框架概览 预训练工具箱MMPretrain Python推理API 环境搭建 O…

数据结构与算法·第4章【串】

串是有限长的字符序列&#xff0c;由一对单引号相括&#xff0c;如: “a string” 可以理解为c的 s t r i n g string string 基本操作 S t r A s s i g n , S t r C o m p a r e , S t r L e n g t h , C o n c a t , S u b S t r i n g StrAssign,StrCompare,StrLength,Conc…

大数据技术——使用IDEA开发Scala程序

目录 一、使用IDEA开发WordCount程序... 3 二、实验目的... 3 三、实验要求... 3 四、实验环境... 3 五、实验步骤... 3 4.1.1启动IDEA并创建一个新项目WordCount 3 4.1.2为WordCount项目添加Scala框架支持... 7 4.1.3数据准备... 8 4.1.4设置项目目录... 9 4.1.5新建…

webAPI学习笔记4——PC端网页特效

目录 1. 元素偏移量 offset 系列 1.1 offset 概述 1.2 offset 与 style 区别 offset style !!&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;案例&#xff1a;获取鼠标在盒子内的坐标 &#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&…

Jeston Orin Nnao 安装pytorch与torchvision环境

大家好&#xff0c;我是虎哥&#xff0c;Jeston Orin nano 8G模块&#xff0c;提供高达 40 TOPS 的 AI 算力&#xff0c;安装好了Jetpack5.1之后&#xff0c;我们需要配置一些支持环境&#xff0c;来为我们后续的深度学习开发提供支持。本章内容&#xff0c;我将主要围绕安装对…

OCR图片文字识别,人工手动图片标注软件安装过程

OCR图片文字识别&#xff0c;人工手动图片标注软件安装过程&#xff0c;本章关注标注软件的安装&#xff0c;启动过程 1. 下载 anaconda anaconda 下载慢的问题&#xff1a; 使用国内镜像地址下载&#xff1a; https://mirrors.bfsu.edu.cn/anaconda/archive/ https://www.ana…

OpenMMLab-AI实战营第二期——4.深度学习预训练与MMPretrain

文章目录 1. MMPreTrain算法库介绍1.1 算法库与任务组成1.2 框架概览 2. 经典主干网络2.1 ResNet2.2 Vision Transformer 3. 自监督学习3.1 SimCLR3.2 MAE3.3 iBOT 4. 多模态算法4.1 CLIP4.2 BLIP 视频链接&#xff1a;b站-深度学习预训练与MMPretrain 1. MMPreTrain算法库介绍…

NvM学习笔记(一)以TC387为例,分析为什么要使用Flash 模拟 EEPROM ?

在嵌入式软件系统中&#xff0c;管理非易失性的数据存储&#xff0c;如在系统启动时&#xff0c;从非易失性存储器中读取一些关键数据&#xff0c;在系统关闭阶段&#xff0c;同步应用程序RAM区的数据到非易失性存储器中&#xff0c;是一项十分必要的工作。 目前行业内用的最广…

Linux :: 时间日历指令【3】:cal 指令:查询当日是今年的第几天、输出当前月历、指定月历、输出当前年历、指定年历

前言&#xff1a;本篇是 Linux 基本操作篇章的内容&#xff01; 笔者使用的环境是基于腾讯云服务器&#xff1a;CentOS 7.6 64bit。 学习集&#xff1a; C 入门到入土&#xff01;&#xff01;&#xff01;学习合集Linux 从命令到网络再到内核&#xff01;学习合集 目录索引&am…

Redis分段锁实现超高并发秒杀

参考尼恩著&#xff1a;《Java高并发核心编程》 技术自由圈 业务情景 还是秒杀场景&#xff0c;假设抖音直播间小杨哥上架6000单螺蛳粉&#xff0c;价格9.9买10包&#xff0c;限时1分钟秒杀&#xff0c;此时准备秒杀的人有1万人。我们首先从技术上来看看如果不进行优化是否可以…