当前位置: 首页 > news >正文

数据结构——静态顺序表,动态顺序表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中⼴泛使 ⽤的 数据结构,常⻅的线性表:顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的, 线性 表在物理上存储时,通常以数组和链式结构的形式存储。

以数组形式存储的线性表又叫做顺序表,以链式结构存储的又叫做链表

顺序表又分为静态顺序表,和动态顺序表;区别在于数组的申请方式,静态方式申请的是静态顺序表,而动态申请的是动态顺序表(malloc或者new)。

静态顺序表的优点是:

1.不需要动态管理内存,代码书写上会比较方便。 2. 没有动态管理内存中申请以及释放空间的时间开销。

缺点是:

1. ⼀旦空间占满,新来的数据就会溢出。 2. 如果为了保险而申请很大的空间,数据量小的情况下,会浪费很多空间。

动态顺序表的优点是:

1.自由的分配空间。数据量小,就只用申请小内存;数据量大,就在原有的基础上扩容。

缺点是:

1.由于需要动态管理内存,代码书写上会比较麻烦。 2. 动态内存的过程中会经常涉及扩容,而扩 容需要申请空间,转移数据,释放空间。 这些操作会有大量的时间消耗。

静态顺序表

顺序表的元素以int类型演示,可以是任何类型

//创建
const int N = 1e6+10;//定义静态顺序表的最大长度
int a[N], n;         //直接创建一个大数组表示顺序表,n是当前有多少个元素

//添加一个元素
//尾插
void push_back(int x)
{
    a[++n] = x;//空出0,看个人习惯
}

//头插
void push_front(int x)
{
    for(int i = n; i >= 1; i--)
    {
        a[i + 1] = a[i];
    }
    a[1] = x; 
    n++; 
}
// 任意位置插⼊ - 在位置 p 处,插⼊⼀个 x
void insert(int p, int x)
{
    for(int i = n; i >= p; i--) // 注意顺序不要颠倒
    {
        a[i + 1] = a[i]; 
    }
    a[p] = x;
    n++; 
}

//删除一个元素
// 头删
void pop_front()
{
     // 把所有元素向前移动⼀位
     for(int i = 2; i <= n; i++) // 顺序不能颠倒
     {
         a[i - 1] = a[i];
     }
     n--; 
}
//尾删
void pop_back()
{
    n--;
}
//任意位置删除
void erase(int p)
{
    for(int i = p + 1; i <= n; i++)
    {
        a[i - 1] = a[i];
    }
    n--;
}

//查找一个元素
//按值查找
// 查找这个数第⼀次出现的位置,找不到返回 0
int find(int x)
{
     for(int i = 1; i <= n; i++)
     {
         if(a[i] == x) return i;
     }
     return 0;
}
//按位查找
// 返回 p 位置的数
int at(int p)
{
     return a[p];
}

//修改元素
// 把 p 位置的数修改成 x
void change(int p, int x)
{
     a[p] = x;
}

// 清空顺序表
void clear()
{
     n = 0;
}

当然,上述代码是有问题的,比如增加元素是数组可能会溢出,删除元素是数组可能是空,查找元素时p要合法,清空顺序表时如果里面的元素是动态申请的要释放……

这种由静态数组来模拟实现的数据结构一般都是用在竞赛中,所以都是输入保证不会出现上述问题。

动态顺序表

头文件 SqList.h

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

typedef int SLDataType;

typedef struct SqList
{
	SLDataType* arr;
	int size;//当前数组元素个数
	int capacity;//数组的长度
}SL;

// 对数据的管理:增删查改
// 初始化顺序表
void SqListInit(SL* ps);
//销毁顺序表
void SqListDestroy(SL* ps);


//打印
void SqListPrint(SL s);

//检查空间是否足够,不够就扩容
void SqListCheck(SL* ps);

//尾插x
void SqListPushBack(SL* ps, SLDataType x);
//头插x
void SqListPushFront(SL* ps, SLDataType x);
//尾部删除
void SqListPopBack(SL* ps);
//头部删除
void SqListPopFront(SL* ps);
//查找元素
int SqListFind(SL s, SLDataType x);
//在下标为pos位置插入x
void SqListInsert(SL* ps, int pos, SLDataType x);
//删除下标为pos位置的元素
void SqListErase(SL* ps, int pos);

 源文件 SqList.c 

#define  _CRT_SECURE_NO_WARNINGS 1
#include"SqList.h"

//初始化
void SqListInit(SL* s)
{
	s->arr = NULL;
	s->size = s->capacity = 0;
}

//打印
void SqListPrint(SL s)
{
	int i = 0;
	for (i = 0; i < s.size; i++)
	{
		printf("%d ", s.arr[i]);
	}
	printf("\n");
}

//检查空间是否足够,不够就扩容
void SqListCheck(SL* ps)
{
	if (ps->size == ps->capacity)//顺序表满了
	{
		//realloc的大小,单位是字节!!!
		//如果原来就为空,那就开1个元素,如果原来不为空,就开为2倍
		int newcapacity = (ps->capacity == 0) ? 4 : 2 * (ps->capacity);
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity*sizeof(SLDataType));//为数组申请空间!!不是结构体
		if (tmp == NULL)//开辟失败
		{
			perror("realloc");
			exit(1);
		}
		//开辟成功
		ps->arr = tmp;  //扩容后的数组
		ps->capacity = newcapacity;//新长度
	}
}

//尾插
void SqListPushBack(SL* ps, SLDataType x)
{
	SqListCheck(ps);
	ps->arr[ps->size++] = x;
}

//头插
void SqListPushFront(SL* ps, SLDataType x)
{
	//断言,防止传空指针
	assert(ps);
	SqListCheck(ps);
	//把整个表向后移动一个位置
	for (int i = ps->size;i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;//元素加1
}

//尾部删除
void SqListPopBack(SL* ps)
{
	//防止顺序表为空
	assert(ps && ps->size);
	ps->size--;
}

//头部删除
void SqListPopFront(SL* ps)
{
	assert(ps && ps->size);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

//查找元素
int SqListFind(SL s, SLDataType x)
{
	for (int i = 0; i < s.size; i++)
	{
		if (s.arr[i] == x)
			return i;
	}
	return -1;//没找到就返回-1
}

//在下标为pos位置插入x
void SqListInsert(SL* ps, int pos, SLDataType x)
{
	SqListCheck(ps);
	assert(pos >= 0 && pos <= ps->size);//取等时是头插或尾插
	for (int i = ps->size; i > pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos] = x;
	ps->size++;
}

//删除下标为pos位置的元素
void SqListErase(SL* ps, int pos)
{
	assert(pos >= 0 && pos <= ps->size - 1);//取等时是头删和尾删
	for (int i = pos; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

//销毁顺序表
void SqListDestroy(SL* ps)
{
	free(ps->arr);
	ps->arr = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

相关文章:

  • 三维重建_点云重建方法及开源框架推荐
  • 基于 IMX6ULL 的环境监测自主调控系统
  • 网络安全-php安全知识点
  • 下载安装umamba教程使用命令
  • 2024 nginx已知 sztu.edu.cn.key和sztu.edu.cn.pem配置ssl
  • AIGC技术助力空军招飞,近屿智能开启智能人才培育新征程
  • Docker 搭建 Nginx 服务器
  • w227springboot旅游管理系统设计与实现
  • leetcode刷题记录(一百一十八)——39. 组合总和
  • clickhouse--本地表和分布式表,副本机制,分片集群
  • c++ 典型练习题
  • MongoDB 查询文档
  • Python解决“数字分组求偶数和”问题
  • 如何实现网关
  • 课程分享 | 安全系统建设的挑战与解决方案
  • 【DeepSeek】CherryStudio + Ollama
  • FreiHAND (handposeX-json 格式)数据集-release >> DataBall
  • Springboot 熔断,穿透,雪崩
  • 网络安全-新型路径攻击流程及防御措施
  • 【论文精读】YOLO-World:实时开放词汇目标检测
  • 侵害孩子者,必严惩不贷!3名性侵害未成年人罪犯被执行死刑
  • 美将解除对叙利亚制裁,外交部:中方一贯反对非法单边制裁
  • 曾犯强奸罪教师出狱后办教培机构?柳州鱼峰区教育局:正核实
  • 人民日报:从“轻微免罚”看涉企执法方式转变
  • 车载抬头显示爆发在即?业内:凭借市场和产业链优势,国内供应商实现反超
  • 汤加附近海域发生6.4级地震