【数据结构和算法】实现线性表中的静态、动态顺序表(上)

简介: 【数据结构和算法】实现线性表中的静态、动态顺序表

本文是数据结构的开篇,上文学习了关于使用C语言实现静态、动态、文件操作的通讯录,其中使用到了结构体这一类型,实际上,是可以属于数据结构的内容,接下来我们来了解一下顺序表的相关内容。

前言

数据结构是什么?

对于大家来说,这是一个全新的内容模块,数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法索引技术有关。

我们接下来是对于数据结构的顺序表的实现的讲解


一、线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

实际上,学会了顺序表和链表,自然栈、队列、二叉树等各种结构就好学啦,又称顺序表和链表是数据结构的基础,是实现后序内容的基础。

一、顺序表是什么?

1.将表中元素一个接一个的存入一组连续的存储单元中,这种存储结构顺序结构

2.使用顺序结构存储的线性表叫做顺序表

总结:

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

二、分析顺序表的实现

顺序表,分为动态和静态两种顺序表,顺序表的实际操作功能大致为,增删改查,又细分为头尾增删,初始化、摧毁顺序表等操作。

我们接下来分别介绍静态和动态顺序表是如何实现的!!!

三、静态顺序表

使用结构体为:

1.顺序表初始化

如图所示:

代码演示:

//初始化函数
void InitSeqtable(Seqtable* st) {
  //for (int i = 0; i < MAX; i++) {
  //  st->date[i] = 0;//初始化为0  实际上可以不用初始化数组
  //}
  st->size = 0;
}

2.增加元素

分为头插入、尾插入

1.尾插

如图所示:

代码演示:

//尾插入
void BackSeqtable(Seqtable* st, int data) {
  //尾部插入的时候要进行判别是否为满
  if (st->size == MAX) {
    //表示满了
    perror("顺序表已经满员,无法插入新数据\n");
    exit(-1);//退出就可以
  }
  //没有满员,就加入数据即可
  st->date[st->size++] = data;
}

2.头插

如图所示:

代码如下:

//头插入
void FrontSeqtable(Seqtable* st, int data) {
  //一样先进行判断是否满员
  if (st->size == MAX) {
    perror("满员无法插入");
    exit(-1);
  }
  //头部插入。就是将原有数据向后移动一个位置
  int num = st->size - 1;
  for (int i = num; i>=0; i--) {
    st->date[i + 1] = st->date[i];
  }
  //while (num>=0) {
  //  st->date[num + 1] = st->date[num];
  //  num--;
  //}
  //最后插入数据
  st->date[0] = data;
  st->size++;
}

3.删除元素

分为头删、尾删

1.尾删

如图所示:

代码如下:

//尾删除
void SeqtablePopBack(Seqtable* st) {
  //尾删除,需要判断是否为空
  assert(st->size > 0);//断言判断
  st->size--;//直接元素个数减去一个就可以
}

2.头删

如图所示:

代码如下:

//头删除
void SeqtablePopFront(Seqtable* st) {
  //头部删除,也要判空
  assert(st->size > 0);//断言
  //将后面的数据覆盖前面的数据
  for (int i = 0; i < st->size-1; i++) {
    st->date[i] = st->date[i + 1];
  }
  st->size--;//size减去一个元素即可
}

4.改变数据和查找

想要改变指定下标的数据,输入要查找的元素,更改这个的数据,要先查找到对应坐标,简易的更改数值,不考虑重复的问题,从左向右的顺序查询

代码如下:

//查找
int SearchSeqtable(Seqtable* st) {
  assert(st->size > 0);//如果为空,不用查找,直接报错
  int num = 0;
  scanf("%d", &num);//输入查找的元素
  for (int i = 0; i < st->size; i++) {
    if (st->date[i] == num) {
      return i;//找到返回下标
    }
  }
  return -1;//没找到返回-1
}
void ChangeSeqtable(Seqtable* st) {
  int num=SearchSeqtable(st);//进入查找,返回下标
  if (num == -1) {
    printf("顺序表中没有该元素,无法修改\n");
    return;
  }
  int a = 0;
  scanf("%d", &a);//输入想要更改的数据
  st->date[num] = a;
}

5.打印和销毁顺序表

代码如下:

//摧毁顺序表
void SeqtableDestory(Seqtable* st) {
  //摧毁的话,静态表直接初始化为0
  st->size = 0;
}
//打印
void PrintSeqtable(Seqtable* st) {
  for (int i = 0; i < st->size; i++) {
    printf("%d ", st->date[i]);
  }
}

四、动态顺序表

动态顺序表和静态顺序表的差别就是结构体、初始化、摧毁顺序表、扩容

结构体如下:

//动态顺序表
typedef struct Seqtable {
  int* data;//数据域
  int size;//个数
  int capacity;//容量
}Seqtable;
//实际上动态顺序表和静态顺序表,只有在初始化、销毁、扩容的时候不一样

1.初始化

//初始化顺序表
void InitSeqtable(Seqtable* st) {
  st->size = st->capacity = 0;
  st->data = NULL;
}

2.扩容

如图所示:

代码演示:

//扩容
void Expansion(Seqtable* st) {
  //1.直接扩容二倍,这样防止后序一致扩容
  int newcapacity = st->capacity = 0 ? 4 : st->capacity * 2;
  int* tmp = (int*)realloc(st->data, newcapacity * sizeof(int));
  if (tmp == NULL) {
    //表示创建失败
    perror("realloc fail\n");
    exit(-1);
  }
  //创建成功  tmp给data
  st->data = tmp;
  st->capacity = newcapacity;
}

如图上,另外一种扩容方法,可以看这篇文章中动态通讯录扩容,里面有介绍(24条消息) 【C语言】使用C语言实现静态、动态的通讯录(简单易懂)_小王学代码的博客-CSDN博客

3.销毁顺序表

void SeqListDestory(Seqtable* ps) {
  free(ps->data);//直接释放a的空间 
  ps->data = NULL;//然后指向NULL
  ps->capacity = ps->size = 0;
}

除此之外,和静态顺序表都差不多一样了

相关文章
|
2月前
|
机器学习/深度学习 传感器 算法
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
194 2
|
3月前
|
传感器 算法 Python
【电机矢量控制算法】基于线性死区补偿的永磁同步电机矢量控制算法仿真
【电机矢量控制算法】基于线性死区补偿的永磁同步电机矢量控制算法仿真
|
3月前
|
机器学习/深度学习 人工智能 算法
【多智能体编队】基于自适应控制算法非线性输入的多智能体系统编队控制研究(Matlab代码复现)
【多智能体编队】基于自适应控制算法非线性输入的多智能体系统编队控制研究(Matlab代码复现)
110 0
|
3月前
|
机器学习/深度学习 算法 数据格式
MARS算法理论和Python代码实现:用分段回归解决非线性时间序列预测问题
本文将深入探讨MARS算法的核心原理,并详细阐述其在时间序列预测任务中的应用策略与技术实现。
240 0
|
4月前
|
存储 监控 安全
企业上网监控系统中红黑树数据结构的 Python 算法实现与应用研究
企业上网监控系统需高效处理海量数据,传统数据结构存在性能瓶颈。红黑树通过自平衡机制,确保查找、插入、删除操作的时间复杂度稳定在 O(log n),适用于网络记录存储、设备信息维护及安全事件排序等场景。本文分析红黑树的理论基础、应用场景及 Python 实现,并探讨其在企业监控系统中的实践价值,提升系统性能与稳定性。
150 1
|
4月前
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
144 0
|
8月前
|
存储 算法 Java
算法系列之数据结构-二叉树
树是一种重要的非线性数据结构,广泛应用于各种算法和应用中。本文介绍了树的基本概念、常见类型(如二叉树、满二叉树、完全二叉树、平衡二叉树、B树等)及其在Java中的实现。通过递归方法实现了二叉树的前序、中序、后序和层次遍历,并展示了具体的代码示例和运行结果。掌握树结构有助于提高编程能力,优化算法设计。
273 10
 算法系列之数据结构-二叉树
|
8月前
|
算法 Java
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
226 3
 算法系列之数据结构-Huffman树
|
7月前
|
存储 前端开发 Java
线性数据结构详解
本文介绍了线性数据结构中的核心概念——节点,以及基于节点构建的链表、队列和栈等重要数据结构。节点是计算机科学中基本的构建单元,包含数据和指向其他节点的链接。通过添加约束或行为,可以构建出单向链表、双向链表、队列和栈等复杂结构。
216 1
|
8月前
|
算法 Java
算法系列之数据结构-二叉搜索树
二叉查找树(Binary Search Tree,简称BST)是一种常用的数据结构,它能够高效地进行查找、插入和删除操作。二叉查找树的特点是,对于树中的每个节点,其左子树中的所有节点都小于该节点,而右子树中的所有节点都大于该节点。
327 22

热门文章

最新文章