【数据结构】顺序表---C语言版

news2024/12/24 3:10:13

【数据结构】顺序表

  • 前言:
  • 一、线性表
  • 二、顺序表
    • 1.顺序表的概念及结构:
    • 2.顺序表的分类:
    • 3.顺序表缺陷:
  • 三、顺序表的代码实现:
    • 1.头文件:
    • 2.函数文件:
    • 3.测试文件:
  • 四、顺序表的相关OJ题:
    • (1)原地移除数组中所有的元素val:
      • 1.题目描述:
      • 2.思路表述:
      • 3.代码实现:
    • (2)删除有序数组中的重复项
      • 1.题目描述:
      • 2.思路表述:
      • 3.代码实现:
    • (3)合并两个有序数组
      • 1.题目描述:
      • 2.思路表述:
      • 3.代码实现:

前言:

顺序表是一种常见的数据结构,今天就让我来带领大家一起学习一下吧!
不会再休息,一分一毫了,OK,let’s go!

一、线性表

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

在这里插入图片描述

二、顺序表

1.顺序表的概念及结构:

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

2.顺序表的分类:

顺序表一般可以分为:

  1. 静态顺序表:使用定长数组存储元素。
//顺序表的静态存储
#define N 7
typedef int SLDataType;
 
typedef struct SeqList
{
	SLDataType array[N];//定长数组
	size_t size;//有效数据的个数
}SeqList;

在这里插入图片描述
2. 动态顺序表:使用动态开辟的数组存储。

typedef struct SeqList
{
	SLDataType* array;//指向动态开辟的数组
	size_t size;//有效数据的个数
	size_t capacity;//容量
}SeqList;

在这里插入图片描述

3.顺序表缺陷:

  1. 顺序表缺陷:

(1)动态增容有性能消耗。

(2)当头部插入数据时,需要挪动数据

三、顺序表的代码实现:

1.头文件:

#pragma once

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

typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* s;//顺序表的名称(头指针!)

	int size;//储存的有效个数!
	int capacity;//整块空间的大小!
}SL;


//初始化
void SLInit(SL* ps);
//销毁
void SLDestory(SL* ps);
//打印
void SLPrint(SL* ps);



//管理数据:增删查改

//尾插
void PushBack(SL* ps, SLDataType x);
//头插
void PushFront(SL* ps, SLDataType x);

//尾删
void PopBack(SL* ps);
//头删
void PopFront(SL* ps);

//判断是否扩容
void SLCheckCapacity(SL* ps);

//在pos位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x);

2.函数文件:

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>
#include "SeqList.h"

//初始化函数
void SLInit(SL* ps)
{
	assert(ps);

	//创建空间
	ps->s = (SLDataType*)malloc(sizeof(SLDataType)*4);
	if (ps->s == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	ps->size = 0;
	ps->capacity = 4;
}

//销毁函数
void SLDestory(SL* ps)
{
	free(ps);

	ps->s = NULL;
	ps->size = ps->capacity = 0;
}

//打印函数
void SLPrint(SL* ps)
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->s[i]);
	}
	printf("\n");
}


//判断是否扩容
void SLCheckCapacity(SL* ps)
{
	assert(ps);

	if (ps->size == ps->capacity)
	{
		//需要扩容
		SLDataType* tmp = (SLDataType*)realloc(ps->s, sizeof(SLDataType) * ps->capacity * 2);//扩大了原来容量的二倍。

		//SLDataType* tmp = (SLDataType*)realloc(ps->s, 2 * ps->capacity);标准的错误写法!
		//如果空间不够用,要对一些元素进行扩容。我们扩容的标准:就是为这些元素申请它 自身大小 整数倍 的空间!所以说为什么要sizeof(数据类型),然后再乘以扩大的容量的倍数
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->s = tmp;
		ps->capacity *= 2;
	}
	
}

//尾插
void PushBack(SL* ps, SLDataType x)
{
	//检查容量
	SLCheckCapacity(ps);

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

//尾删
void PopBack(SL* ps)
{
	assert(ps);

	ps->size--;

}

//头插(利用一个end指针从后往前拷贝!)
void PushFront(SL* ps, SLDataType x)
{
	assert(ps);

	//检查容量
	SLCheckCapacity(ps);

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


//头删
void PopFront(SL* ps)
{
	assert(ps);

	int begin = 0;
	while (begin < ps->size-1)
	{
		ps->s[begin] = ps->s[begin + 1];
		begin++;
	}
	ps->size--;
}


//在pos位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x)

{
	assert(ps);
	assert(pos >= 0 && pos < ps->size);

	SLCheckCapacity( ps);

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

3.测试文件:

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>
#include "SeqList.h"



void test1()
{
	SL s1;
	SLInit(&s1);

	PushFront(&s1, 1);
	PushFront(&s1, 2);
	PushFront(&s1, 3);
	PushFront(&s1, 4);
	PushFront(&s1, 5);

	SLPrint(&s1);

	PopFront(&s1);
	PopFront(&s1);
	PopFront(&s1);

	SLPrint(&s1);

}


void test2()
{
	SL s2;

	SLInit(&s2);

	PushBack(&s2,1);
	PushBack(&s2,2);
	PushBack(&s2,3);
	PushBack(&s2,4);
	PushBack(&s2,5);

	SLPrint(&s2);

	PopBack(&s2);
	PopBack(&s2);
	PopBack(&s2);

	SLPrint(&s2);
}


void test3()
{
	SL s2;

	SLInit(&s2);

	PushBack(&s2, 1);
	PushBack(&s2, 2);
	PushBack(&s2, 3);
	PushBack(&s2, 4);
	PushBack(&s2, 5);

	SLPrint(&s2);

	SLInsert(&s2, 3, 6);//在下标为3的数据之前插入一个6

	SLPrint(&s2);
}

int main()
{

	//test1();//测试头插,头删

	//test2();//测试尾插 尾删

	test3();//测试在pos位置之前插入数据!
	return 0;

}

在这里插入图片描述

四、顺序表的相关OJ题:

(1)原地移除数组中所有的元素val:

1.题目描述:

1.原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)。OJ链接:OJ链接
在这里插入图片描述

2.思路表述:

在这里插入图片描述

3.代码实现:

int removeElement(int* nums, int numsSize, int val) 
{
    int src=0;
    int dst=0;
    while(src<numsSize)
    {
        if(nums[src]!=val)
        {
            nums[dst++]=nums[src++];
        }
        else
        {
            src++;
        }
    }
    return dst;//返回的是:新数组的长度,因为最后一步出循环的时候,dst已经++了,所以说直接返回dst就行了
}

(2)删除有序数组中的重复项

1.题目描述:

在这里插入图片描述

2.思路表述:

还使用双下标法:
在这里插入图片描述

3.代码实现:

int removeDuplicates(int* nums, int numsSize) 
{
    int dst=1;
    int src=0;
    while(dst<numsSize)
    {
        if(nums[dst]!=nums[src])
        {
          //nums[++src]=nums[dst++];//这里的src一定要是前置++,先++,然后再赋值。
          
          src++;
          nums[src]=nums[dst];
          dst++;
        }
        else
        {
            
            dst++;
        }
    }
    return src+1;
}

(3)合并两个有序数组

1.题目描述:

在这里插入图片描述

2.思路表述:

使用3下标法
在这里插入图片描述

3.代码实现:

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) 
{
   int end1=m-1;
   int end2=n-1;
   int end=m+n-1;
   while(end1>=0&&end2>=0)
   {
       if(nums1[end1]>nums2[end2])
       {
           nums1[end--]=nums1[end1--];
       }
       else
       {
           nums1[end--]=nums2[end2--];
       }
   }
   //因为用nums1的初始长度是m+n,所以不会担心数组大小不够用。
   //下面这个循环是针对:比如说nums1中的所有数字都插到自己数组后面了,但是因为两个数组都是有序的,所以我只需要把nums2中的全部数字依次放到nums1前面就行了。
   while(end2>=0)
   {
       nums1[end--]=nums2[end2--];
   }
}

好了,今天的分享就到这里了
如果对你有帮助,记得点赞👍+关注哦!
我的主页还有其他文章,欢迎学习指点。关注我,让我们一起学习,一起成长吧!

在这里插入图片描述

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

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

相关文章

私域成交的方式---朋友圈成交

朋友圈不止是生活&#xff0c;也是工作营销的很好场所。朋友圈成交也就是私域成交中养客户成交。和之前的微商相似&#xff0c;微商就是在朋友圈发内容&#xff0c;引起客户的兴趣&#xff0c;再转到1对1私聊进行成交。 适合产品&#xff1a;所有的产品都适合&#xff0c;不管…

Python实现艺术设计?提取图片中颜色并绘制成可视化图表,从大师作品中提取配色方案

文章目录 导入模块并加载图片提取颜色并整合成表格绘制图表实战环节关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠…

android基于UDP实现聊天小功能

一、DatagramSocket DatagramSocket 是 Java 中用于发送和接收 UDP 数据包的类。它提供了创建和管理 UDP 套接字的功能。以下是 DatagramSocket 类的一些常用方法&#xff1a; DatagramSocket(): 创建一个未绑定到特定本地地址和端口的 DatagramSocket 实例。 DatagramSocket…

普乐蛙绵阳科博会一场VR科普航天科学盛宴科普知识

普乐蛙绵阳科普展&#xff1a;一场科学盛宴&#xff0c;点燃孩子探索欲望的火花! 普乐蛙绵阳科普展正在如火如荼地进行中&#xff0c;吸引了无数孩子和家长的热情参与。这场科普盛宴以独特的内外视角&#xff0c;让人们感受到科学的魅力&#xff0c;激发了孩子们对知识的渴望和…

蚁剑低版本反制

蚁剑低版本反制 漏洞概述 中国蚁剑是一款开源的跨平台网站管理工具&#xff0c;它主要面向于合法授权的渗透测试安全人员以及进行常规操作的网站管理员。影响范围 AntSword <2.0.7 蚁剑实验版本&#xff1a;2.0.7 环境搭建&#xff1a; 172.16.1.233&#xff08;蓝队服…

如何在 Photoshop 中制作金像

如何使用渐变贴图和一些鲜为人知的 Photoshop 图像效果在 Photoshop 中制作金像 1. 如何为图像添加噪点 步骤 1 首先&#xff0c;将“颜色填充”图层设置为淡蓝色 #a9c9dd 颜色。 步骤 2 接下来&#xff0c;让我们右键单击>创建智能对象&#xff0c;以防万一我们以后想要…

【EasyExcel】导出excel并支持自定义设置数据行背景颜色等

需求背景&#xff1a; 根据查询条件将列表数据导出&#xff0c;并筛选出满足某个条件的数据&#xff0c;将满足条件的数据的背景颜色设置成黄色。 &#xff08;本文例子如&#xff1a;name出现的次数大于等于2&#xff0c;将相关数据背景颜色都设置为黄色&#xff09; …

代码签名证书是如何保护软件?

随着互联网的普及和技术的发展&#xff0c;软件开发已经成为了一个非常重要的行业。然而&#xff0c;软件安全问题也日益凸显&#xff0c;恶意软件、病毒、木马等威胁着用户的数据安全和隐私。为了确保软件的安全和可靠性&#xff0c;开发者需要采取一系列措施来保护他们的产品…

在线教育行业内卷突围,持续激活平台用户体验是关键

在线教育并不等同于K12教育。 众所周知&#xff0c;越来越卷的考试制度&#xff0c;已经被家长、学生们的谩骂和吐槽淹没了好几层。各种减负、杜绝课后补课等条例纷纷出台&#xff0c;不断的挤压着K12教育企业的生存空间。 于是乎&#xff0c;大家都认为&#xff0c;在线教育…

笔记62:注意力汇聚 --- Nadaraya_Watson 核回归

本地笔记地址&#xff1a;D:\work_file\&#xff08;4&#xff09;DeepLearning_Learning\03_个人笔记\3.循环神经网络\第10章&#xff1a;动手学深度学习~注意力机制 a a a a a a a a a a a a a a a a

一键换肤功能

使用css3的css变量来实现 示例&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name&qu…

好用的IDEA插件推荐

前言 Idea 是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;它可以帮助开发人员更加高效地编写、调试和部署软件应用程序,Idea 还具有许多插件和扩展&#xff0c;可以根据开发人员的需要进行定制和扩展&#xff0c;从而提高开发效率,今天我们就来介绍一款…

使用opencv的matchTemplate进行银行卡卡号识别

![字体文件](https://img-blog.csdnimg.cn/3a16c87cf4d34aceb0778c4b20ddadb2.png#pic_center import cv2 import numpy as npdef show_img(img, name"temp"):img cv2.resize(img, (0, 0), fx3, fy3)cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()de…

Windows10-用户账户控制、Windows远程桌面

Windows10用户账户控制怎么设置白名单 问题引出&#xff1a; 安装低版本搜狗输入法后经常弹出用户账户控制 解决方案&#xff1a; 全局模式&#xff1a; UAC控制最早出现在Windows Vista中&#xff0c;用户帐户控制&#xff08;UAC&#xff09;是一项旨在防止对您的计算机…

2024年进入-1/12的世界

1.从一段与AI的对话开始 cj: 1234...无限的&#xff0b;下去结果是无穷大吗&#xff1f; chatgpt: 是的&#xff0c;从常规的数学观点来看&#xff0c;级数 1234… 无限相加的结果是正无穷。 这是因为每一项都是正数&#xff0c;并且随着项数的增加&#xff0c;部分和会趋近…

校园虚拟化部署与横向扩展统一存储

项目背景 这所隶属教育部直属重点大学&#xff0c;学校设有11个学科体系&#xff0c;现有本硕博学生共29000余人&#xff0c;为积极响应“中国教育现代化2023战略部署”&#xff0c;校方制定教育信息化2.0发展目标&#xff0c;通过平台融合&#xff0c;数据驱动、技术赋能等措…

时间序列预测 — LSTM实现单变量滚动风电预测(Keras)

目录 1 数据处理 1.1 数据集简介 1.2 数据集处理 2 模型训练与预测 2.1 模型训练 2.2 模型滚动预测 2.3 结果可视化 1 数据处理 1.1 数据集简介 实验数据集采用数据集5&#xff1a;风电机组运行数据集&#xff08;下载链接&#xff09;&#xff0c;包括风速、风向、温…

【MySQL】binlog数据恢复

binlog概述 binlog二进制日志记录保存了所有执行过的修改操作语句&#xff0c;不保存查询操作。如果 MySQL 服务意外停止&#xff0c;可通过二进制日志文件排查&#xff0c;用户操作或表结构操作&#xff0c;从而来恢复数据库数据。binlog 是逻辑日志&#xff0c;记录的是这个…

网页设计--第5次课后作业

1、快速学习JavaScript的基本知识第1-10章 JavaScript入门 - 绿叶学习网 2、使用所学的知识完成以下练习。需求如下3个&#xff1a; 1&#xff09;点亮灯泡 2&#xff09;将所有的div标签的标签体内容后面加上&#xff1a; very good 3&#xff09;使所有的复选框呈现被选…

编程在现代社会中的重要性

文章目录 编程的重要性引言编程在现代社会中的重要性常见的编程应用场景结语 编程的重要性 引言 编程在现代社会中的重要性是不言而喻的&#xff0c;它可以让我们创造出各种有用的软件&#xff0c;解决各种复杂的问题&#xff0c;甚至改变世界。 编程在现代社会中的重要性 编…