顺序表实现—数据结构

news2024/12/27 13:59:40

文章目录

  • 一、顺序表概念及结构
  • 二、动态顺序表和静态顺序表的选择
  • 三、动态顺序表的实现逻辑
    • (1)创建结构体
    • (2)具体函数实现
      • (*)顺序表初始化
      • (*)释放顺序表
      • (*)打印顺序表
      • (*)是否需要扩容
      • (*)顺序表尾插
      • (*) 顺序表头插
      • (*)顺序表尾插删除
      • (*)顺序表头插删除
      • (*)顺序表查找
      • (*)顺序表在pos位置插入x
      • (*)顺序表删除pos位置的值
  • 四、动态顺序表实现代码
    • (1)test.c
    • (2)SeqList.h
    • (3)SeqList.c
  • 五、动态顺序表测试结果

一、顺序表概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删。一般分为静态顺序表和动态顺序表。

二、动态顺序表和静态顺序表的选择

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以我们实现动态顺序表。

三、动态顺序表的实现逻辑

(1)创建结构体

typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;
	int size;
	int capacity; 
}SL;

使用动态顺序表先创建结构体是必须的,先使用typedef int SLDateType;是为了方便改类型,在结构体里创建三个成员变量,SLDateType* a,为了方便增容,用指针的形式,int size代表a指向空间里的个数,int capacity代表a指向空间里的容量。

(2)具体函数实现

(*)顺序表初始化

void SeqListInit(SL* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;

}

先用assert断言,为了更方便查看在哪个地方出错,初始化就是把ps指向的结构体成员变量a置为空指针,size和capacity置为0。

(*)释放顺序表

void SeqListDestroy(SL* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

释放顺序表也就是把a指向的空间的释放掉,并把a置为空指针,而另外两个成员变量置为0。

(*)打印顺序表

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

打印顺序表只需要用for循环依次打印,用ps找到size,即成员个数,再用printf进行打印,ps找到数组a。

(*)是否需要扩容

void if_add(SL*ps)
{
	if (ps->capacity == ps->size)
	{
		int NewCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDateType* tmp = (SLDateType*)realloc(ps->a, NewCapacity*sizeof(SLDateType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = NewCapacity;
	}
}

为了提高代码的可读性,把是否需要扩容封装一个函数,而且下面有好多函数需要用到。
先判断capacity和size是否相等,如果相等,说明需要增容,再用三目运算符判断capacity是否等于0,如是则设置一个有一定大小的初始值,反之,则指定的倍数进行扩容。再把它赋给Newcapacity,再realloc进行开辟空间,用另外一个指针tmp表示,再判断tmp是否为空,如是则用perror显示开辟失败,并非正常退出程序exit(-1),反之则把新指针再赋给原来的a,最后capacity进行更新,Newcapacity赋给capacity。

(*)顺序表尾插

void SeqListPushBack(SL* ps, SLDateType x)
{
	assert(ps);
	if_add(ps);
	ps->a[ps->size] = x;
	ps->size++;
}

尾插先判断空间是否足够,再把x依次插入ps->size元素下标的位置,并进行ps->size加加,记录已尾插的个数。

(*) 顺序表头插

void SeqListPushFront(SL* ps, SLDateType x)
{
	assert(ps);
	if_add(ps);
	for (int i = ps->size - 1; i >=0; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[0] = x;
	ps->size++;
}

头插也是先判断空间是否足够,再从后面进行尾插,用for循环从i=ps->size开始,每头插一个就把此位置的值往后移,直到第一个位置也就是0位置可用的时候,在把x赋给0位置处,直到i<0为止,最后size加加。

(*)顺序表尾插删除

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

头删,需要用asser断言一下,里面的内容为ps->size>0,防止size<0,以便告诉我们在哪出错,最后直接ps->szie–

(*)顺序表头插删除

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

头插删除,直接用for循环把后面内容往前移,注意i是从1开始的,如果写成0会越界,而且也只能从1开始,因为删除的是开头的元素,最后ps->szie–。

(*)顺序表查找

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

顺序表查找返回值是int类型,返回的是下表元素,那就用for循环直接遍历,如果找到x,就返回下标元素i,最后遍历完也没有找到返回-1。
这个函数需要结合测试函数test.c的部分代码用,如下,如果返回不是-1,就打印下标元素i,否则打印失败。

int ret = SeqListFind(&sl, 6);
	  if (ret!=-1)
	  {
		  printf("%d\n", ret);

	  }
	  else
	  {
		  printf("find fail\n");
	  }

(*)顺序表在pos位置插入x

void SeqListInsert(SL* ps, int pos, SLDateType x)
{
	assert(ps);
	assert(pos <= ps->size);
	if_add(ps);
	for (int i = ps->size-1; i >= pos; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[pos] = x;
	ps->size++;
}

顺序表在下标元素pos插入x,先写两个断言函数,pos不能比szie大,因为我们是在size个数里面插入,再判断是否需要扩容,再用for循环进行移动元素,初始位置为当前数组的最后一个元素开始,直到pos结束,也就是pos位置可用可插入的时候再进行插入x,最后size++。

(*)顺序表删除pos位置的值

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

顺序表删除下标pos位置的值,同上用assert进行断言,从
pos位置开始,进行覆盖,直到ps->size-1结束,防止越界,因为有可能capacity等于size,最后size–。

四、动态顺序表实现代码

(1)test.c

#include"SeqList.h"

int main()
{
      SL sl;
	  SeqListInit(&sl);

	  SeqListPushBack(&sl, 1);
	  SeqListPushBack(&sl, 2);
	  SeqListPushBack(&sl, 3);
	  SeqListPushBack(&sl, 4);
	  SeqListPrint(&sl);

	  SeqListPopBack(&sl);
	  SeqListPopBack(&sl);
	  SeqListPopBack(&sl);
	  SeqListPrint(&sl);

	  SeqListPushFront(&sl,3);
	  SeqListPushFront(&sl, 4);
	  SeqListPushFront(&sl, 5);
	  SeqListPrint(&sl);

	  SeqListPopFront(&sl);
	  SeqListPopFront(&sl);
	  SeqListPrint(&sl);

	  int ret = SeqListFind(&sl, 6);
	  if (ret!=-1)
	  {
		  printf("%d\n", ret);

	  }
	  else
	  {
		  printf("find fail\n");
	  }

	  SeqListInsert(&sl, 1, 4);
	  SeqListPrint(&sl);

	  SeqListInsert(&sl, 3, 6);
	  SeqListPrint(&sl);

	  SeqListErase(&sl, 2);
	  SeqListPrint(&sl);

	  SeqListDestroy(&sl);
	  return 0;
}

(2)SeqList.h

#pragma once//防止头文件包含
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int SLDateType;
typedef struct SeqList
{
	SLDateType* a;
	int size;
	int capacity; 
}SL;
void SeqListInit(SL* ps);//顺序表初始化
void SeqListDestroy(SL* ps);//释放顺序表

void SeqListPrint(SL* ps);//打印顺序表
void SeqListPushBack(SL* ps, SLDateType x);//顺序表尾插
void SeqListPushFront(SL* ps, SLDateType x); //顺序表头插
void SeqListPopFront(SL* ps);//顺序表头插删除
void SeqListPopBack(SL* ps);//顺序表尾插删除
void if_add(SL* ps);//是否需要扩容

int SeqListFind(SL* ps, SLDateType x);//顺序表查找
void SeqListInsert(SL* ps, int pos, SLDateType x); 顺序表在pos位置插入x
void SeqListErase(SL* ps, int pos);// 顺序表删除pos位置的值

(3)SeqList.c

#include"SeqList.h"
void SeqListInit(SL* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;

}
void SeqListDestroy(SL* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}
void SeqListPrint(SL* ps)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}
void if_add(SL*ps)
{
	if (ps->capacity == ps->size)
	{
		int NewCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDateType* tmp = (SLDateType*)realloc(ps->a, NewCapacity*sizeof(SLDateType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = NewCapacity;
	}
}
void SeqListPushBack(SL* ps, SLDateType x)
{
	assert(ps);
	if_add(ps);
	ps->a[ps->size] = x;
	ps->size++;
}
void SeqListPopBack(SL* ps)
{
	assert(ps->size > 0);
	ps->size--;
}
void SeqListPushFront(SL* ps, SLDateType x)
{
	assert(ps);
	if_add(ps);
	for (int i = ps->size - 1; i >=0; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[0] = x;
	ps->size++;
}
void SeqListPopFront(SL* ps)
{
	assert(ps);
	for (int i = 1; i < ps->size; i++)
	{
		ps->a[i-1] = ps->a[i];
	}
	ps->size--;
}
int SeqListFind(SL* ps, SLDateType x)
{
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

void SeqListInsert(SL* ps, int pos, SLDateType x)
{
	assert(ps);
	assert(pos <= ps->size);
	if_add(ps);
	for (int i = ps->size-1; i >= pos; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[pos] = x;
	ps->size++;
}
void SeqListErase(SL* ps, int pos)
{
	assert(ps && pos < ps->size);
	for (int i = pos; i < ps->size-1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->size--;
}

五、动态顺序表测试结果

在这里插入图片描述

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

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

相关文章

青少年python系列 21.turtle库绘制一个8

#绘制一个8import turtle#上方的小圆&#xff0c;圆心在左turtle.circle(80)#下方的大圆&#xff0c;圆心在右turtle.circle(-100)turtle.done() 青少年python教学视频ppt源码 青少年python系列目录_老程序员115的博客-CSDN博客 csdn文章推荐受影响解决办法10个字10行 csdn文…

梦开始的地方—— C语言指针入门

文章目录指针入门1.指针概念2. 指针和指针类型3. 野指针造成野指针的原因如何避免野指针4. 指针的运算指针加减整数指针的运算关系指针的关系运算5.指针和数组6. 二级指针7. 指针数组指针入门 1.指针概念 指针(Pointer) 是编程语言中的一个对象&#xff0c;利用地址&#xff…

31、Java——JDBC实现账号密码登录

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;乐趣国学的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java案例分…

Kong自动注册kong-spring-boot-stater

前言 kong-spring-boot-stater框架是为了解决SpringBoot项目和kong网关的自动注册&#xff0c;虽然Kong网关有提供可视化管理后台的操作界面&#xff0c;但是在多服务、多环境的时候在管理后台挨个配置每个服务节点是比较麻烦的&#xff0c;所以这也是kong-spring-boot-stater…

P3654 First Step (ファーストステップ)——暴力枚举

First Step (ファーストステップ) 题目背景 知らないことばかりなにもかもが&#xff08;どうしたらいいの&#xff1f;&#xff09; 一切的一切 尽是充满了未知数&#xff08;该如何是好&#xff09; それでも期待で足が軽いよ&#xff08;ジャンプだ&#xff01;&#xff09…

项目流程管理工具:OmniPlan Pro 4 中文

如何更好的管理项目流程&#xff1f;OmniPlan Pro 4中文是个很好的帮手&#xff0c;非常好用的项目流程管理工具&#xff0c; 强大的规划&#xff0c;管理复杂性&#xff1a; 引入三个新的内置模板&#xff1a;标准项目、标准项目&#xff08;样式&#xff09;和简单项目。 …

【TA】Unity角色二次元风格渲染

NRMToonLitSample Author : 文若 我的Demo地址 &#xff1a; NRMToonLitSample 学习视频地址 &#xff1a; Kerry大佬的 技术美术实战培训课程——卡通人物渲染方案 文章目录NRMToonLitSample1. 模型贴图基本信息2. 基础渲染效果2.1 基础shader Toon2.2 光照模型效果第一步&…

【从零到一的Raspberry】树莓派踩坑实录(一)系统安装与简单开发

写在前面 本系列作为树莓派上手记录&#xff0c;同时将本人的踩坑以及参考进行记录汇总&#xff0c;必要时罗列出小组分工&#xff0c;作为《嵌入式软开》小组参考文件。 0 硬件准备 名称描述树莓派3B支持wifi&#xff0c;包含了散热器、外壳、电源线等配件网线感谢王emo同学…

【小程序websocket前后端交互】uniapp写微信小程序聊天功能功能,websocket交互功能,心跳重连【详细注释,复制即用】

前言 这几天在做的一个需求&#xff0c;就是要写一个小程序端的页面&#xff0c;用于跟客服聊天。 然后就用到了websocket技术&#xff0c;以前我做过网页版的&#xff0c;但是做小程序后发现网页版的逻辑放过来没问题&#xff0c;但是很多的方法和api是不生效的&#xff0c;所…

立方体的表面积 长方体的表面积 公里转换为米 温度对照

立方体的表面积 难度&#xff1a;青铜 时间限制&#xff1a;1秒 占用内存&#xff1a;64 M 输入立方体边长&#xff0c;输出立方体的表面积。不考虑非法输入。格式 输入格式&#xff1a;输入实型 输出格式&#xff1a;输出实型 #include<bits/stdc.h> using namespace s…

万字长文的CSS与JavaScript简易学习

近期学习web笔记&#xff0c;可供参考 目录 css: css导入方式&#xff1a; css选择器&#xff1a; javascript: javascript介绍&#xff1a; js引入方式&#xff1a; js书写语法&#xff1a; js变量&#xff1a; 5种原始类型&#xff1a; 运算符&#xff1a; JavaScr…

推荐一款基于.Net Core开发简约漂亮的 WPF UI库

今天给大家推荐一个开源WPF UI库。 项目简介 这是一款使用简单、UI评论的WPF UI库&#xff0c;借鉴了多个开源框架。UI简单清晰、大气。 技术架构 1、跨平台&#xff1a;这是基于.Net Core开发的系统&#xff0c;可以部署在Docker, Windows, Linux, Mac。 2、开发环境&…

微视网媒:沃尔沃质量有什么魅力 让大佬罗永浩、樊登纷纷翻牌S90?

在消费市场&#xff0c;选对代言人&#xff0c;产品就成功了一半&#xff0c;这话可是一点都没说错。 从一定程度上来说&#xff0c;代言人就是产品对外形象的展示&#xff0c;甚至有不少消费者还会因为代言人激情下单。 当然&#xff0c;成也代言&#xff0c;败也代言&#xf…

拉格朗日对偶问题的一些介绍

文章目录参考前言拉格朗日函数例1例2拉格朗日函数的对偶问题参考 “拉格朗日对偶问题”如何直观理解&#xff1f;“KKT条件” “Slater条件” “凸优化”打包理解 感觉有时间看视频的还是看视频比较好&#xff0c;本文只是记录一下以防以后忘记。 前言 还记得SVM里用到拉格朗…

Python代码的编写运行方式简介

Python代码的编写运行方式简介 Python编写方式 Python 是一种解释型的脚本编程语言&#xff0c;支持两种代码编写方式&#xff1a;交互命令行方式和运行.py代码文件方式。 Python的交互命令行方式和直接运行.py代码文件方式有什么区别呢&#xff1f; 交互模式&#xff0c;相当…

Python爬虫|采集开源众包的悬赏任务,自动翻页

前言 现在互联网,有很多网站提供一些接单外派的形式,提供给有能力的人或者团队去接单。比如说,很多人熟悉的猪八戒,程序员客栈,CODING 码市,开源众包等等平台,相信很多同学也都知道。 如果要第一时间了解某个接单平台发布的第一手悬赏任务,选择爬虫也是非常不错的选择…

websocket接口自动化集成pytest测试框架

01、websocket协议 1、介绍 WebSocket是一种在单个TCP通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455&#xff0c;并由RFC7936补充规范。WebSocket API也被W3C定为标准。 WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务端主动向…

【2020-10-26】JS逆向之同盾滑块

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言总结前言 用官网的做个例子吧&#xff1a;https://sec.xiaodun.com/onlineExperience/slidingPuzzle?Rbdjj?sourcetongdun&keywordtongdun 简单分析下这个…

项目整体管理

项目整体管理 1.1 项目整体管理概述 1.项目整体管理知识领域包括识别、确定、结合、统一与协调各项目管理过程组内不同过程与项目管理活动所需进行的各种过程和活动。 2.“整体管理”的基本任务就是为了按照实施组织确定的程序实现项目目标&#xff0c;将项目管理过程组中需要…

CalBioreagents 艾美捷芽孢杆菌多克隆抗体说明书

艾美捷CalBioreagents 芽孢杆菌多克隆抗体英文说明&#xff1a; CATALOG NUMBER: P043 PRODUCT DESCRIPTION: Rabbit anti-Bacillus polyclonal antibody. IMMUNOGEN: Immunogen was prepared from a pool of purified spores from Bacillus subtilis and Bacillus cereus.…