首页 > 其他分享 >数据结构:详解【顺序表】的实现

数据结构:详解【顺序表】的实现

时间:2024-03-13 15:33:28浏览次数:23  
标签:ps 顺序 void pos 详解 SL 数据结构 size

1. 顺序表的定义

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。动态顺序表与数组的本质区别是——根据需要动态的开辟空间大小。

2. 顺序表的功能

动态顺序表的功能一般有如下几个:

  • 初始化顺序表
  • 打印顺序表中的数据
  • 检查顺序表的容量
  • 顺序表头部插入数据
  • 顺序表尾部插入数据
  • 顺序表头部删除数据
  • 顺序表尾部删除数据
  • 顺序表任意位置插入数据
  • 顺序表任意位置删除数据
  • 顺序表中查找数据
  • 顺序表中修改指定位置数据

3.顺序表各功能的实现

3.1 创建顺序表

typedef int SQDateType;//对int进行重命名,可增加代码的普适性。

typedef struct SeqList
{
	SQDateType* a;
	size_t size; //有效数据
	size_t capacity;//容量的空间大小
}SL;//对这个结构体重命名为SL,书写方便

在这里插入图片描述

3.2 初始化顺序表
由于建立顺序表后并没有原始空间,所以我们自行动态开辟空间,又因为后续要进行扩容,所以我们必须初始化容量大小。

void SeqListInit(SL*ps)
{
	ps->a = (SQDateType*)malloc(sizeof(SQDateType) * 4);//初始化开辟4个int类型的空间
	//检查是否开辟成功
	if (ps->a == NULL)
	{
		printf("malloc fail!\n");
		return;
	}
	ps->capacity = 4;//初始化容量大小为4
	ps->size = 0;
}

3.3 打印顺序表中的数据
对顺序表进行增删查改等操作后,我们要把数据打印在控制台以便观察。

void SeqListPrint(SL* ps)
{
	//判断顺序表中是否有数据
	assert(ps->size > 0);
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

3.4 检查顺序表的容量
对顺序表进行插入(增加)数据的操作时,我们必须先对顺序表进行容量的检查,若容量不够,则扩容。
并且扩容的幅度一般是原来容量的2倍。

void CheckSeqListCapacity(SL*ps)
{
	assert(ps);//断言
	//检查容量是否已满
	if (ps->capacity == ps->size)
	{
		//扩容
		SQDateType* tmp = (SQDateType*)realloc(ps->a, ps->capacity * 2 * sizeof(SQDateType*));
		if (tmp == NULL)
		{
			printf("realloc fail!\n");
			return;
		}
		else
		{
			ps->a = tmp;
			ps->capacity *= 2;//容量增大为原来的两倍
		}
	}
}

3.5 顺序表头部插入数据
头插,意思是在顺序表的最前面插入一个数据。我们需要把顺序表里的原数据(如果原来有数据的话)从后往前向后挪一个空间,再把要插入的数据放到第一个位置即可。
![在这里插入图片描述](/i/ll/?i=direct/1b879d6df276406d8a11e8655d9e8cb0.png
代码实现如下:

void SeqListPushFront(SL* ps, SQDateType x)
{
     assert(ps);
	//检查是否要扩容
	CheckSeqListCapacity(ps);

	int end = ps->size;
	for (end = ps->size ; end >0; end--)
	{
		ps->a[end] = ps->a[end - 1];
	}
	ps->a[end] = x;
	ps->size++;//有效数据+1
}

3.6 顺序表尾部插入数据
尾插,意思是在顺序表的最后面插入一个数据。只需要找到该位置的下标(ps->size处)直接插入即可。
![在这里插入图片描述](/i/ll/?i=direct/11372c84deae44a7b1dc038142252cc9.png

代码实现如下:

void SeqListPushBack(SL* ps, SQDateType x)
{
     assert(ps);
     //检查是否要扩容
	CheckSeqListCapacity(ps);

	ps->a[ps->size] = x;
	ps->size++;//有效数据+1
}

3.7 顺序表头部删除数据
头删,意思是删除一个顺序表最前面的数据。只需把原数据从前往后开始向前覆盖一个空间即可。
![在这里插入图片描述](/i/ll/?i=direct/589b3cd1ddcc4189be625c3189619a32.png

代码实现如下:

void SeqListPopFront(SL* ps)
{
	assert(ps->size > 0);//断言,当顺序表内有数据时才删除
	
	for (int start = 0; start < ps->size; start++)
	{
		ps->a[start] = ps->a[start + 1];
	}
	ps->size--;//有效数据-1
}

3.8 顺序表尾部删除数据
尾删,直接删除顺序表中最后一个数据即可。

void SeqListPopBack(SL* ps)
{
	assert(ps->size > 0);
	ps->size--;//有效数据-1
}

3.9 顺序表任意位置插入数据
在顺序表的pos位置处插入一个数据,先要把pos处及其后面的原数据向后挪一个空间,再把数据放入pos处。
在这里插入图片描述
代码实现如下:

void SeqListInsert(SL* ps, int pos, SQDateType x)
{
	assert(ps && pos < ps->size);//pos<size时才满足
	CheckSeqListCapacity(ps);

	int end = ps->size ;
	for (end = ps->size ; end > pos; end--)
	{
		ps->a[end] = ps->a[end-1];
	}
	ps->a[pos] = x;//在pos的位置放入数据
	ps->size++;//有效数据+1
}

3.10 顺序表任意位置删除数据
在顺序表的pos位置处删除一个数据,只要把pos处后面的数据向前覆盖一个空间。
在这里插入图片描述
代码实现如下:

void SeqListEarse(SL* ps, int pos)
{
	assert(ps && pos < ps->size);//pos<size时才满足
	int start = pos;
	for (start = pos; start < ps->size; start++)
	{
		ps->a[start] = ps->a[start + 1];
	}
	ps->size--;//有效数据-1
}

3.11 顺序表中查找数据
把顺序表中的数据循环遍历,判断每个数据与查找数据是否相等,若相等,返回1,否则返回-1。

int  SeqListFind(SL* ps, SQDateType x)
{
	assert(ps && ps->size > 0);//表中有数据时才能查找
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
		{
			return 1;
			break;
		}
	}
	return -1;
}

3.12 顺序表中修改指定位置数据
只要在顺序表中找到指定位置,把修改的值赋给它即可。

void SeqListModify(SL* ps, int pos, SQDateType x)
{
	assert(ps && pos < ps->size);//要修改的位置要小于数据个数
	ps->a[pos] = x;
}

4. 完整代码

SeqList.h

#pragma once

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

typedef int SQDateType;

typedef struct SeqList
{
	SQDateType* a;
	size_t size; //有效数据
	size_t capacity;//容量的空间大小
}SL;

//初始化顺序表
void SeqListInit(SL* ps);

//头部插入数据
void SeqListPushFront(SL* ps, SQDateType x);

//尾部插入数据
void SeqListPushBack(SL* ps, SQDateType x);

//头部删除数据
void SeqListPopFront(SL* ps);

//尾部删除数据
void SeqListPopBack(SL* ps);

//任意位置插入数据
void SeqListInsert(SL* ps, int pos,SQDateType x);

//任意位置删除数据
void SeqListEarse(SL* ps, int pos);

//打印数据函数
void SeqListPrint(SL* ps);

//查找数据
int SeqListFind(SL* ps, SQDateType x);

//修改指定位置数据
void SeqListModify(SL* ps, int pos, SQDateType x);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 

#include "SeqList.h"

void SeqListInit(SL*ps)
{
	ps->a = (SQDateType*)malloc(sizeof(SQDateType) * 4);//初始化开辟4个int类型的空间
	if (ps->a == NULL)
	{
		printf("malloc fail!\n");
		return;
	}
	ps->capacity = 4;
	ps->size = 0;
}

void CheckSeqListCapacity(SL*ps)
{
	assert(ps);
	//检查容量是否已满
	if (ps->capacity == ps->size)
	{
		//扩容
		SQDateType* tmp = (SQDateType*)realloc(ps->a, ps->capacity * 2 * sizeof(SQDateType*));
		if (tmp == NULL)
		{
			printf("realloc fail!\n");
			return;
		}
		else
		{
			ps->a = tmp;
			ps->capacity *= 2;
		}
	}
}


void SeqListPushFront(SL* ps, SQDateType x)
{
	assert(ps);
	CheckSeqListCapacity(ps);

	int end = ps->size;
	for (end = ps->size ; end >0; end--)
	{
		ps->a[end] = ps->a[end - 1];
	}
	ps->a[end] = x;
	ps->size++;
}

void SeqListPrint(SL* ps)
{
	//判断顺序表中是否有数据
	assert(ps->size > 0);
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

void SeqListPushBack(SL* ps, SQDateType x)
{
	CheckSeqListCapacity(ps);

	ps->a[ps->size] = x;
	ps->size++;
}

void SeqListPopFront(SL* ps)
{
	assert(ps->size > 0);
	for (int start = 0; start < ps->size; start++)
	{
		ps->a[start] = ps->a[start + 1];
	}
	ps->size--;
}

void SeqListPopBack(SL* ps)
{
	assert(ps->size > 0);
	ps->size--;
}

void SeqListInsert(SL* ps, int pos, SQDateType x)
{
	assert(ps && pos < ps->size);
	CheckSeqListCapacity(ps);

	int end = ps->size ;
	for (end = ps->size ; end > pos; end--)
	{
		ps->a[end] = ps->a[end-1];
	}
	ps->a[pos] = x;
	ps->size++;
}

void SeqListEarse(SL* ps, int pos)
{
	assert(ps && pos < ps->size);
	int start = pos;
	for (start = pos; start < ps->size; start++)
	{
		ps->a[start] = ps->a[start + 1];
	}
	ps->size--;
}

int  SeqListFind(SL* ps, SQDateType x)
{
	assert(ps && ps->size > 0);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
		{
			return 1;
			break;
		}
	}
	return -1;
}

void SeqListModify(SL* ps, int pos, SQDateType x)
{
	assert(ps && pos < ps->size);
	ps->a[pos] = x;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 

#include "SeqList.h"

void SeqListTest()
{
	SL sl;
	
	//在这里调用各数据接口(函数)进行测试
}

int main()
{

	SeqListTest();

	return 0;
}

标签:ps,顺序,void,pos,详解,SL,数据结构,size
From: https://blog.csdn.net/2301_77900444/article/details/136661725

相关文章

  • 多重背包详解,二进制优化、单调队列优化
    文章目录零、前言一、多重背包初步1.1问题描述1.2朴素算法二、朴素算法的优化策略2.1二进制优化2.1.1算法思想2.2二进制优化的正确性证明2.3代码实现2.2单调队列优化2.2.1算法思想2.2.2代码实现2.3、总结三、OJ练习3.1P1776宝物筛选3.1.1原题链接3.1.2思路分析3.1.3......
  • Spring Boot 2.x中配置文件加载顺序分析
    一般springboot2.x的配置有多种方式,如resources文件夹中可以定义bootstrap.yml(或bootstrap.properties)、application.yml(或application.properties)、配置中心(如nacos),那么它们加载顺序是怎样的,如何使用?bootstrap.yml:首先加载bootstrap.yml(或bootstrap.properties)。这个......
  • 【数据结构初阶 9】内排序
    文章目录......
  • 数据结构与算法学习(01)交换函数的指针陷阱
    先看以下正确的例子 voidswap(int*px,int*py){inttemp;temp=*px;/*间接取*/*px=*py; /*间接取,间接存*/*py=temp; /*间接存*/}int main(void){inta=2,b=3;swap(&a,&b);printf("a=%d,b=%d",a,b);return......
  • 数据结构算法系列----背包问题(01,完全,多重)
    一、01背包1、01背包介绍    "01背包"是一个经典的动态规划问题。在01背包中,给定一个背包容量和一组物品,每个物品都有自己的重量和价值。问题的目标是选择一些物品放入背包中,使得放入的物品总重量不超过背包容量,同时使得放入的物品总价值最大。    "01"表......
  • 数据结构算法系列----快速幂
    一、快速幂的介绍:1、为什么要使用快速幂:   当我们计算a的n次幂时,最先想到的肯定是c中的内置函数  pow(a,n),这个内置函数虽然简单方便,但是在实际使用中这个函数的时间复杂度是o(n),因为它是将a乘n次得到的答案。  由于在n非常大时用pow()很容易超时,因此我们引入一个时......
  • Offer必备算法13_路径dp_六道力扣题详解(由易到难)
    目录①力扣62.不同路径解析代码②力扣63.不同路径II解析代码③力扣LCR166.珠宝的最高价值解析代码④力扣931.下降路径最小和解析代码⑤力扣64.最小路径和解析代码⑥力扣174.地下城游戏解析代码本篇完。①力扣62.不同路径62.不同路径难度中等一个......
  • 十分钟掌握分布式数据库开发:OpenMLDB 开发者镜像详解
    OpenMLDB是一款国产的、开源的、面向时序数据的分布式内存数据库系统,它专注于高性能、高可靠性和易扩展性,适用于海量时序数据的处理以及在线特征的实时计算。在大数据和机器学习的浪潮中,OpenMLDB以其强大的数据处理能力和高效的机器学习支持,在开源数据库领域崭露头角。OpenMLDB......
  • 开题顺序(暴搜&dfs)---牛客小白月赛69-C
    #include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#defineendl'\n'#defineinf0x3f3f3f3fconstintN=2e5+5;intn,t,p;inta[N],b[N],c[N],x[N],y[N];intres,vis[N];voiddfs(ints,intm){ res=max(res,s); for(inti=1;i......
  • 详解Go程序添加远程调用tcpdump功能,exec.Command("sh", "-c", "ps -elf | grep xxx |
    摘自:https://www.jb51.net/article/249001.htm这篇文章主要介绍了go程序添加远程调用tcpdump功能,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 最近开发的telemetry采集系统上线了。听起来高大上,简单来说就是一个grpc/udp服务端,用......